60

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

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

我尝试使用- (WKNaviation *)loadRequest:(NSURLRequest *)request,但它没有被调用。

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

4

7 回答 7

126

我自己一直在寻找一个很好的解释,但还没有找到。我在我的应用程序中使用了以下内容,一切似乎都有效(编辑:根据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 桥。所以看看我的另一个答案。

于 2014-10-01T05:59:23.593 回答
75

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

于 2015-01-27T22:48:26.843 回答
37

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

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

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

    decisionHandler(WKNavigationActionPolicyAllow);
}
于 2015-02-25T14:00:44.470 回答
18

重新阅读您的描述,您实际上需要了解的是如何使用 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"});
于 2014-10-07T02:33:24.243 回答
12

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>
于 2016-06-30T07:51:03.327 回答
7

对于swift 4.2:(取自 Yifei He 何一非。)

 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
        }

    }
于 2018-12-27T10:23:29.920 回答
1

您可以为您的 WKWebView 添加观察者

 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"];
}
于 2014-10-16T10:48:19.963 回答