UIWebView的委托方法shouldStartLoadWithRequest:相当于WKWebView?
我的iOS 7+应用程序中有一个模块,它是一个UIWebView。 该HTML页面加载一个JavaScript,创build自定义形状的button(使用Raphaeljs库)。 使用UIWebView,我将委托设置为self。 每次按下我的自定义button时,都会调用委托方法webView: shouldStartLoadWithRequest: navigationType:
请求不应该由html处理,而应该由iOS代码处理。 所以我使用了“inapp”作为我的请求的scheme的请求约定(在这里读取stackoverflow的地方)。 然后我检查主机并采取适当的行动。
这个代码可以在iOS 7上正常工作。但是,在iOS 8上,web视图显示为空白(bug?),所以我决定使用WKWebView for iOS 8设备。 网页视图现在渲染罚款(和惊人的更快!),但我的button没有任何效果。
我尝试使用- (WKNaviation *)loadRequest:(NSURLRequest *)request
,但它不被调用。
我无法findUIWebView委托方法webView: shouldStartLoadWithRequest: navigationType:
的直接等价物webView: shouldStartLoadWithRequest: navigationType:
用WKWebView处理这些请求的最好方法是什么?
重新阅读你的描述,看起来你真正需要知道的是如何使用WKWebView重新实现Javascript / Objective-C桥接。
WKWebView有一个内置的Javascript和Objective-C / Swift: WKScriptMessageHandler
。
首先,在你的视图控制器的头文件中包含WebKit头文件和WKScriptMessageHandler
协议:
#import <UIKit/UIKit.h> #import <WebKit/WebKit.h> @interface ViewController : UIViewController <WKScriptMessageHandler> @end
在初始化你的WKWebView
,你需要用一个脚本消息处理器来configuration它。 任何你想要的名称,但对我来说,它似乎是命名为您的应用程序是有道理的。
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:
做的工作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中。 这些方法在每个请求(包括初始请求)之前被调用,并提供允许/禁止的能力。
我一直在寻找一个好的解释,但没有find一个。 我已经在我的应用程序中使用了以下内容,似乎一切正常( 编辑:基于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桥接。 所以看看我的其他答案。
只要使用下面的方法,它是WKNavigationDelegate的一部分
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURLRequest *request = navigationAction.request; NSString *url = [[request URL]absoluteString]; decisionHandler(WKNavigationActionPolicyAllow); }
在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添加Observer
static void* keyValueObservingContext = &keyValueObservingContext; [webView addObserver:self forKeyPath:@"URL" options:0 context:keyValueObservingContext]; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"URL"]){ // do something } }
不要忘记在viewWillDisappear中删除它
-(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [webView removeObserver:self forKeyPath:@"URL"]; }