Mac WebView使用(API+JS交互)

本文介绍了在MacOS开发中如何在WebView中实现JavaScript与Objective-C的交互。关键步骤包括添加WebKit.framework,设置WebView的代理,定义JS可调用的Objective-C对象,以及声明和实现Objective-C端供JS调用的函数。同时提到了在不同SDK版本间可能存在的兼容性问题,并给出了解决方案。


//屏蔽右键
- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
{
    NSLog(@"fonction==%s\n",__FUNCTION__);
    return nil;
}

#pragma mark -
#pragma mark - WebFrameLoadDelegate
//-当页面准备加载新的的URL,调用。
//如果成功,回调 WebResourceLoadDelegate-- willSendRequest
//如果不成功,回调didFailProvisionalLoadWithError
- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
{
    
    NSLog(@"fonction==%s\n",__FUNCTION__);

}


//加载WebResourceLoadDelegate willSendRequest 不成功 出错回调
-(void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
{
    
    NSLog(@"fonction==%s\n",__FUNCTION__);
    
    isBundleHtmlLoad = NO;
    
}

//-页面完成加载里调用
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
    NSLog(@"fonction==%s\n",__FUNCTION__);

}

//-系统无法自身完成webView UI加载调用
-(void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
{
    NSLog(@"fonction==%s\n",__FUNCTION__);

}



#pragma mark - WebResourceLoadDelegate
//-保存当前请求的 Http地址
-(NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
{
    
    if ([request.URL.relativeString hasPrefix:@"http"])
    {
        histroyURL = request.URL;
    }
    NSLog(@"fonction==%s\n",__FUNCTION__);

    return request;
}

- (void)webView:(WebView *)sender resource:(id)identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource
{
    NSLog(@"fonction==%s\n",__FUNCTION__);
}


//当资源未能加载时调用
- (void)webView:(WebView *)sender resource:(id)identifier didFailLoadingWithError:(NSError *)error fromDataSource:(WebDataSource *)dataSource
{
    //忽略未加载完成URL错误
    if (error.code == NSURLErrorCancelled)
    {
        return ;
    }

    NSLog(@"fonction==%s\n",__FUNCTION__);
    [self bundleHtml];

}

- (void)webView:(WebView *)sender plugInFailedWithError:(NSError *)error dataSource:(WebDataSource *)dataSource
{
    NSLog(@"fonction==%s\n",__FUNCTION__);

}



#pragma mark - WebPolicyDelegate
- (void)webView:(WebView *)webView unableToImplementPolicyWithError:(NSError *)error frame:(WebFrame *)frame
{
    NSLog(@"fonction==%s\n",__FUNCTION__);
}



Mac下开发WebView 中的 JS交互

转自:http://blog.youkuaiyun.com/perry_xiao/article/details/8027249

MacOS开发中WebView已经实现了浏览器的基本功能,使用十分方便,要在WebView中实现JS调用Obj-c的代码个人觉的需要一下几个基本步骤:

1. 要使用WebView需要添加WebKit.framework。

2. 在Window中添加WebView之后需要在右侧属性的connection设置frameLoadDelegate, resourceLoadDelegate, UIDelegate。

3. 定义一个JS中可是别的变量(如external)用于调用Obj-c代码。

[plain]  view plain  copy
  1. - (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject {  
  2.   
  3.     [windowScriptObject setValue:self forKey:@"external"];  
  4. }  

4.1 在Obj-c中声明对JS开放的函数。

[plain]  view plain  copy
  1. + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector {  
  2.   
  3.     if ( selector == @selector(Login:password:)) {  
  4.         return NO;  
  5.     }  
  6.     return YES;  
  7. }  

4.2 建立命名索引。

[plain]  view plain  copy
  1. + (NSString *) webScriptNameForSelector:(SEL)sel {  
  2.   
  3.     if (sel == @selector(Login:password:)) {  
  4.         return @"Login";  
  5.     }  
  6.     return nil;  
  7. }  

在JS中只要使用external.Login(account, password)就是调用Obj-c中的[self Login:account password:password]。

5.1 在Obj-c中声明对JS开放的变量,其中Result是Obj-c的变量。

[plain]  view plain  copy
  1. + (BOOL) isKeyExcludedFromWebScript:(const char *)name {  
  2.       
  3.     if (strcmp(name, "Result") == 0) {  
  4.         return NO;  
  5.     }  
  6.       
  7.     return YES;  
  8. }  

5.2 建立变量索引。

[plain]  view plain  copy
  1. + (NSString *) webScriptNameForKey:(const char *)name {  
  2.       
  3.     if (strcmp(name, "Result") == 0) {  
  4.         return @"js_result";  
  5.     }  
  6.     return nil;  
  7. }  
如果JS中使用相同的变量名则该函数中可以不再声明。JS中按external.js_result就能访问并修改Obj-c的Result变量。

需要注意的一点是xcode SDK10.7中对变量的索引做的更智能些,而SDK10.6如果JS对Obj-c的变量赋值类型不统一可能会使程序崩溃,因此在SDK从10.7切换到10.6就可能出问题,一种偷懒的方法是将Obj-c的变量定义为id。

上述几个函数是在非正式协议WebScripting中定义的。

实现Obj-c调用JS的代码可以使用如下函数实现,scriptStr中是合法的JS代码:

[plain]  view plain  copy
  1. NSString * resultStr = [theWebView stringByEvaluatingJavaScriptFromString: scriptStr];  

参考:

Xcode帮助文档中有个CallJS工程实现了这些基本功能。




<think>我们正在讨论在Python中集成WebView组件并实现现代浏览器功能。根据用户问题,我们需要使用一个能够嵌入现代浏览器(如基于Chromium的浏览器)的WebView库。在Python中,有几个库可以实现这个功能:1.`pywebview`:一个轻量级的跨平台库,使用系统自带的WebView组件(在Windows上使用Edge,在macOS使用WebKit,在Linux上使用WebKitGTK)。不过,系统自带的WebView可能不是最新的Chromium版本。2.`cefpython`:基于ChromiumEmbeddedFramework(CEF),可以嵌入完整的Chromium浏览器,支持最新的Web技术(如HTML5,CSS3,JavaScript等)。3.`PyQt5`或`PySide2`中的`QWebEngineView`:Qt框架的Web引擎,也是基于Chromium,功能强大。用户要求“现代浏览器功能”,这意味着可能需要支持最新的Web标准、开发者工具(DevTools)等。因此,我们更倾向于使用基于Chromium的解决方案,如`cefpython`或`QWebEngineView`。由于用户没有指定GUI框架,我们可以提供两种方案:方案一:使用`cefpython`(直接嵌入Chromium)方案二:使用`PyQt5`的`QWebEngineView`下面分别给出两种方案的示例代码。###方案一:使用cefpython首先需要安装cefpython:`pipinstallcefpython3`示例代码:```pythonimportcefpython3ascefimportplatformimportsysdefmain():sys.excepthook=cef.ExceptHook#ToshutdownallCEFprocessesonerrorsettings={"window_title":"ModernBrowserinPython",#可以设置窗口大小和其他参数}cef.Initialize(settings=settings)browser=cef.CreateBrowserSync(url="https://example.com",window_title=settings["window_title"])cef.MessageLoop()cef.Shutdown()if__name__=='__main__':main()```注意:cefpython打包后的应用体积较大,因为它包含了Chromium。###方案二:使用PyQt5的QWebEngineView首先安装PyQt5:`pipinstallpyqt5`示例代码:```pythonimportsysfromPyQt5.QtCoreimportQUrlfromPyQt5.QtWidgetsimportQApplication,QMainWindowfromPyQt5.QtWebEngineWidgetsimportQWebEngineViewclassBrowserWindow(QMainWindow):def__init__(self):super().__init__()self.setWindowTitle("ModernBrowserinPython")self.resize(1024,768)self.browser=QWebEngineView()self.browser.load(QUrl("https://example.com"))self.setCentralWidget(self.browser)if__name__=="__main__":app=QApplication(sys.argv)window=BrowserWindow()window.show()sys.exit(app.exec_())```在PyQt5的WebEngineView中,默认已经支持了现代浏览器功能,包括JavaScript、HTML5等。如果需要开发者工具,可以启用:```python#在BrowserWindow类中,可以添加一个方法来打开开发者工具defopen_dev_tools(self):self.browser.page().settings().setAttribute(QWebEngineSettings.WebAttribute.DeveloperExtrasEnabled,True)self.browser.page().triggerAction(QWebEnginePage.InspectElement)```但是注意,开发者工具窗口需要另外处理(比如作为独立窗口打开)。###总结两种方案都可以实现现代浏览器功能。选择建议:-如果希望应用体积小且不介意使用系统自带的WebView(可能不是最新),可以考虑`pywebview`(但这里用户要求现代浏览器功能,所以可能不够)。-如果需要最新的Chromium功能和完整的控制(比如访问底层API),选择`cefpython`。-如果已经在使用Qt框架,或者希望有一个完整的GUI解决方案,选择`PyQt5`或`PySide2`的`QWebEngineView`。根据用户的需求,我们更推荐使用`cefpython`或`PyQt5`方案。生成相关问题:§§相关问题§§1.如何在PythonWebView中执行JavaScript代码?2.如何让Python与WebView中的JavaScript进行交互?3.在PythonWebView中如何调试网页?4.使用cefpython或PyQt5的WebEngineView时,如何解决打包后体积过大的问题?5.在Linux系统中,这些WebView组件有什么特别需要注意的地方?</think>在 Python 中实现 WebView 组件并集成现代浏览器功能,主要通过以下两种方案实现: ### 方案一:使用 `pywebview` 库(推荐) `pywebview` 是一个轻量级跨平台库,封装了系统原生 WebView 组件,支持现代浏览器功能: ```python import webview # 创建浏览器窗口 window = webview.create_window( title="Python 现代浏览器", url="https://example.com", # 可替换为本地HTML文件路径 width=1200, height=800, confirm_close=True # 关闭确认 ) # 启用开发者工具(需在创建窗口后调用) window.evaluate_js('console.log("开发者工具已启用")') # 启动应用 webview.start( private_mode=False, # 禁用隐私模式(允许存储cookies) http_server=True, # 启用本地HTTP服务器 debug=True # 开启调试模式 ) ``` **现代浏览器功能支持**: 1. **JavaScript 交互**: ```python # Python → JavaScript window.evaluate_js('alert("来自Python的消息")') # JavaScript → Python(通过绑定函数) def py_handler(data): print("JS传递的数据:", data) window.expose(py_handler) ``` 在JS中调用:`py_handler("Hello Python")` 2. **开发者工具**: - Windows/Mac:自动支持开发者工具(右键检查元素) - Linux:需安装 `webkit2gtk-drivers` 3. **高级功能**: ```python # 自定义用户代理 webview.start(user_agent="MyCustomAgent/1.0") # 拦截网络请求 def intercept_request(request): if "blocked.com" in request.url: return webview.BLOCK window.events.loading += intercept_request ``` ### 方案二:使用 `PyQt5 WebEngine` 基于 Chromium 的完整浏览器引擎,适合需要深度定制场景: ```python from PyQt5.QtCore import QUrl from PyQt5.QtWidgets import QApplication from PyQt5.QtWebEngineWidgets import QWebEngineView app = QApplication([]) # 创建浏览器组件 browser = QWebEngineView() browser.load(QUrl("https://example.com")) browser.setWindowTitle("PyQt5 现代浏览器") browser.resize(1200, 800) browser.show() # 启用开发者工具(需单独窗口) browser.page().settings().setAttribute( QWebEngineSettings.WebAttribute.DeveloperExtrasEnabled, True ) # 执行JavaScript browser.page().runJavaScript('console.log("Chromium引擎已启动")') app.exec_() ``` ### 关键对比 | 特性 | `pywebview` | `PyQt5 WebEngine` | |---------------------|--------------------------------------|---------------------------------| | 底层引擎 | 系统原生(Edge/WebKit) | Chromium | | 安装大小 | ~5MB | ~100MB | | 现代Web标准支持 | ★★★★ | ★★★★★ | | 开发者工具 | 系统原生支持 | 内置Chromium DevTools | | 跨平台 | Windows/macOS/Linux | Windows/macOS/Linux | | 与Python交互易用性 | 简单API | 需Qt信号槽机制 | ### 部署注意事项 1. **Windows打包**: ```bash pip install pyinstaller pyinstaller --add-data "web;web" --onefile app.py # 包含网页资源 ``` 2. **Linux依赖**: ```bash # Ubuntu/Debian sudo apt install libwebkit2gtk-4.0-dev libgtk-3-dev ``` 3. **安全限制**: ```python # 禁用危险API(防止XSS攻击) window = webview.create_window(js_api=None) # 禁用JS调用Python ``` > **最佳实践**:对于轻量级应用首选 `pywebview`,需要完整浏览器功能时选择 `PyQt5 WebEngine`。两者均支持ES6、WebGL、WebRTC等现代特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值