我的iOS 7+应用程序中有一个模块,它是一个UIWebView.html页面加载了一个创建自定义形状按钮的JavaScript(使用Raphaeljs库).使用UIWebView,我将委托设置为self.webView: shouldStartLoadWithRequest: navigationType:
每次按下我的一个自定义按钮时,都会调用委托方法.请求不应由html处理,而是由iOS代码处理.所以我使用了一个请求约定(在这里读取stackoverflow),使用"inapp"作为我的请求的方案.然后我检查主机并采取适当的措施.
这段代码在iOS 7上运行正常.但是iOS 8上的Web视图显示为空白(bug?),所以我决定使用WKWebView for iOS 8设备.Web视图现在渲染得很好(而且速度更快!),但我的按钮没有任何效果.
我尝试过使用- (WKNaviation *)loadRequest:(NSURLRequest *)request
,但没有调用.
我找不到UIWebView委托方法的直接等价物webView: shouldStartLoadWithRequest: navigationType:
.使用WKWebView处理这些请求的最佳方法是什么?
我自己一直在寻找一个好的解释,但还没找到.我在我的应用程序中使用了以下内容,一切似乎都有效(编辑:根据ccoroom的评论更新):
UIWebViewDelegate - webView:shouldStartLoadWithRequest:navigationType: WKNavigationDelegate - webView:decidePolicyForNavigationAction:decisionHandler:
这是其他UIWebViewDelegate
方法:
UIWebViewDelegate - webViewDidStartLoad: WKNavigationDelegate - webView:didCommitNavigation: UIWebViewDelegate - webViewDidFinishLoad: WKNavigationDelegate - webView:didFinishNavigation: UIWebViewDelegate - webView:didFailLoadWithError: WKNavigationDelegate - webView:didFailNavigation:withError: - webView:didFailProvisionalNavigation:withError:
我喜欢有人为我证实这一点.
编辑:实际上,我已经回答了你在标题中提到的问题(尽管我不再相信webView:didCommitNavigation:
在生命周期中的同一点被调用),但重新阅读你的描述它看起来就像你真正需要的那样知道如何使用WKWebView重新实现Javascript/Objective-C桥.那么看看我的另一个答案.
在Swift中,您可以执行以下操作:
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) { switch navigationAction.request.URLString { case "http://action.is.needed/some-action": self.someFunc() decisionHandler(.Cancel) break default: decisionHandler(.Allow) break } }
这是网页中的链接:
<a href="http://action.is.needed/some-action">Hello world!</a>
重新阅读您的描述看起来您真正需要了解的是如何使用WKWebView重新实现Javascript/Objective-C桥接.
我刚刚完成了这个,按照http://tetontech.wordpress.com/2014/07/17/objective-c-wkwebview-to-javascript-and-back/上的教程和http://上的信息nshipster.com/wkwebkit/
WKWebView有一种内置的Javascript和Objective-C/Swift之间的通信方式:WKScriptMessageHandler
.
首先,WKScriptMessageHandler
在视图控制器的标题中包含WebKit标头和协议:
#import <UIKit/UIKit.h> #import <WebKit/WebKit.h> @interface ViewController : UIViewController <WKScriptMessageHandler> @end
初始化时WKWebView
,需要使用脚本消息处理程序对其进行配置.把它命名为你想要的任何东西,但对我而言,似乎为你的应用程序命名它是有道理的.
WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init]; [theConfiguration.userContentController addScriptMessageHandler:self name:@"myApp"]; _theWebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:theConfiguration]; [_theWebView loadRequest:request]; [self.view addSubview:_theWebView];
现在,实施userContentController:didReceiveScriptMessage:
.当您的webview收到消息时会触发此消息,因此它会执行您之前使用的工作webView:shouldStartLoadWithRequest:navigationType:
.
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { NSDictionary *sentData = (NSDictionary *)message.body; NSString *messageString = sentData[@"message"]; NSLog(@"Message received: %@", messageString); }
您现在已准备好接收来自Javascript的消息.你需要添加到你的Javascript函数调用是这样的:
window.webkit.messageHandlers.myApp.postMessage({"message":"Hello there"});
要回答原始问题,webView:shouldStartLoadWithRequest:navigationType:
UIWebView中的等价物是webView:decidePolicyForNavigationAction:decisionHandler:
在WKWebView中.在每个请求发出之前调用这些方法(包括初始请求)并提供允许/禁止它的能力.
对于SWIFT 4.2:(从逸飞他???服用。)
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) { let url = navigationAction.request.url let urlStr = url?.absoluteString switch urlStr { case BASE_URL: //self.someFunc() decisionHandler(.cancel) break default: decisionHandler(.allow) break } }
只需使用以下方法,它就是WKNavigationDelegate的一部分
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURLRequest *request = navigationAction.request; NSString *url = [[request URL]absoluteString]; decisionHandler(WKNavigationActionPolicyAllow); }