UIWebView委托方法shouldStartLoadWithRequest:在WKWebView中等效?

时间:2014-09-30 19:42:38

标签: ios objective-c uiwebview wkwebview

我的iOS 7+应用程序中有一个模块,它是一个UIWebView。 html页面加载了一个创建自定义形状按钮的JavaScript(使用Raphaeljs库)。使用UIWebView,我将委托设置为self。每次按下我的一个自定义按钮时,都会调用委托方法webView: shouldStartLoadWithRequest: navigationType:。请求不应由html处理,而是由iOS代码处理。所以我使用" inapp"使用了一个请求约定(在这里读取stackoverflow上的某处)作为我的要求的计划。然后我检查主持人并采取适当的行动。

此代码在iOS 7上运行良好。但是iOS 8上的Web视图显示为空白(错误?),因此我决定将WKWebView用于iOS 8设备。网页视图现在渲染得很好(而且速度更快!),但我的按钮没有效果。

我尝试使用- (WKNaviation *)loadRequest:(NSURLRequest *)request,但未调用。

我无法找到UIWebView委托方法webView: shouldStartLoadWithRequest: navigationType:的直接等价物。使用WKWebView处理这些请求的最佳方法是什么?

7 个答案:

答案 0 :(得分:75)

我自己一直在寻找一个好的解释,但是找不到一个。我在我的应用中使用了以下内容,一切似乎都有效(编辑:根据ccoroom's comment更新):

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桥。那么看看我的另一个答案。

答案 1 :(得分:68)

要回答原始问题,在WKWebView中,UIWebView中的webView:shouldStartLoadWithRequest:navigationType:相当于webView:decidePolicyForNavigationAction:decisionHandler:。在每个请求发出之前调用这些方法(包括初始请求),并提供允许/禁止它的能力。

答案 2 :(得分:27)

只需使用以下方法,它就是WKNavigationDelegate的一部分

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURLRequest *request = navigationAction.request;
    NSString *url = [[request URL]absoluteString];

    decisionHandler(WKNavigationActionPolicyAllow);
}

答案 3 :(得分:10)

重新阅读您的描述看起来您真正需要了解的是如何使用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

首先,在视图控制器的标题中包含WebKit标头和WKScriptMessageHandler协议:

#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface ViewController : UIViewController <WKScriptMessageHandler>

@end

初始化WKWebView时,需要使用脚本消息处理程序对其进行配置。把它命名为你想要的任何东西,但对我而言,似乎为你的app命名它是有意义的。

    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"});

答案 4 :(得分:8)

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>

答案 5 :(得分:2)

对于 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
        }

    }

答案 6 :(得分:0)

您可以为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"];
}