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