我的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处理这些请求的最佳方法是什么?
答案 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"];
}