UIWebView delegate method shouldStartLoadWithRequest: equivalent in WKWebView?

前端 未结 7 829
忘掉有多难
忘掉有多难 2020-12-12 14:37

I have a module inside my iOS 7+ app which is a UIWebView. The html page loads a javascript that creates custom-shaped buttons (using the Raphaeljs library). With UIWebView,

相关标签:
7条回答
  • 2020-12-12 14:49

    Just use the following method , it's a part of WKNavigationDelegate

    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
        NSURLRequest *request = navigationAction.request;
        NSString *url = [[request URL]absoluteString];
    
        decisionHandler(WKNavigationActionPolicyAllow);
    }
    
    0 讨论(0)
  • 2020-12-12 14:58

    I've been looking for a good explanation myself, but haven't found one. I've used the following in my app and everything seems to work (Edit: updated based on ccoroom's comment):

    UIWebViewDelegate     - webView:shouldStartLoadWithRequest:navigationType:
    WKNavigationDelegate  - webView:decidePolicyForNavigationAction:decisionHandler:
    

    Here's the other UIWebViewDelegate methods:

    UIWebViewDelegate     - webViewDidStartLoad:
    WKNavigationDelegate  - webView:didCommitNavigation:
    
    UIWebViewDelegate     - webViewDidFinishLoad:
    WKNavigationDelegate  - webView:didFinishNavigation:
    
    UIWebViewDelegate     - webView:didFailLoadWithError:
    WKNavigationDelegate  - webView:didFailNavigation:withError:
                          - webView:didFailProvisionalNavigation:withError:
    

    I'd love for someone to confirm this for me though.

    Edit: Actually, I've answered the question you had in the title (although I'm no longer confident that webView:didCommitNavigation: is called at the exact same point in the lifecycle), but re-reading your description it looks like what you actually need to know about is how to reimplement a Javascript/Objective-C bridge using WKWebView. So have a look at my other answer.

    0 讨论(0)
  • 2020-12-12 15:02

    You can add Observer for your 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
      }
    }
    

    Don't forget to remove it in viewWillDisappear

    -(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [webView removeObserver:self forKeyPath:@"URL"];
    }
    
    0 讨论(0)
  • 2020-12-12 15:06

    Re-reading your description it looks like what you actually need to know about is how to reimplement a Javascript/Objective-C bridge using WKWebView.

    I've just done this myself, following the tutorial at http://tetontech.wordpress.com/2014/07/17/objective-c-wkwebview-to-javascript-and-back/ and the info at http://nshipster.com/wkwebkit/

    WKWebView has a built-in way of communicating between Javascript and Objective-C/Swift: WKScriptMessageHandler.

    First, include the WebKit headers and WKScriptMessageHandler protocol in your view controller's header:

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

    The when initialising your WKWebView, you need to configure it with a script message handler. Name it whatever you want, but to me it seems like naming it for your app makes sense.

        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];
    

    Now, implement userContentController:didReceiveScriptMessage:. This fires when your webview receives a message, so it does the work you were previously doing with webView:shouldStartLoadWithRequest:navigationType:.

    - (void)userContentController:(WKUserContentController *)userContentController 
                            didReceiveScriptMessage:(WKScriptMessage *)message {
        NSDictionary *sentData = (NSDictionary *)message.body;
        NSString *messageString = sentData[@"message"];
        NSLog(@"Message received: %@", messageString);
    }
    

    You're now ready to receive messages from Javascript. The function call you need to add to your Javascript is this:

    window.webkit.messageHandlers.myApp.postMessage({"message":"Hello there"});
    
    0 讨论(0)
  • 2020-12-12 15:08

    To answer the original question, the equivalent of webView:shouldStartLoadWithRequest:navigationType: in UIWebView is webView:decidePolicyForNavigationAction:decisionHandler: in WKWebView. These methods are called before each request is made (including the initial request) and provide the ability to allow/disallow it.

    0 讨论(0)
  • 2020-12-12 15:12

    In Swift you can do something like this:

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

    And this is the link in web page:

    <a href="http://action.is.needed/some-action">Hello world!</a>
    
    0 讨论(0)
提交回复
热议问题