ios UIWebView 委托方法 shouldStartLoadWithRequest:等效于 WKWebView?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26128815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIWebView delegate method shouldStartLoadWithRequest: equivalent in WKWebView?
提问by invalidArgument
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, I set delegate to self. The delegate method webView: shouldStartLoadWithRequest: navigationType:
is called each time one of my custom button is pressed. The requests should not be handled by the html, but rather by the iOS code. So I used a request convention (read somewhere here on stackoverflow) using "inapp" as the scheme of my requests. I then check for the host and take the appropriate action.
我的 iOS 7+ 应用程序中有一个模块,它是一个 UIWebView。html 页面加载一个创建自定义形状按钮的 javascript(使用 Raphaeljs 库)。使用 UIWebView,我将委托设置为 self。webView: shouldStartLoadWithRequest: navigationType:
每次按下我的自定义按钮之一时都会调用委托方法。请求不应由 html 处理,而应由 iOS 代码处理。所以我使用了一个请求约定(在 stackoverflow 上的某处阅读),使用“inapp”作为我的请求方案。然后我检查主机并采取适当的措施。
This code works fine on iOS 7. But the web views appear blank on iOS 8 (bug?), so I decided to use WKWebView for iOS 8 devices. The web views now render fine (and amazingly faster!), but my buttons have no effect.
此代码在 iOS 7 上运行良好。但 Web 视图在 iOS 8 上显示为空白(错误?),因此我决定将 WKWebView 用于 iOS 8 设备。Web 视图现在渲染得很好(而且速度快得惊人!),但我的按钮没有效果。
I tried using - (WKNaviation *)loadRequest:(NSURLRequest *)request
, but it's not called.
我尝试使用- (WKNaviation *)loadRequest:(NSURLRequest *)request
,但它没有被调用。
I can't find a direct equivalent of the UIWebView delegate method webView: shouldStartLoadWithRequest: navigationType:
. What's the best way of handling those requests with WKWebView?
我找不到 UIWebView 委托方法的直接等价物webView: shouldStartLoadWithRequest: navigationType:
。使用 WKWebView 处理这些请求的最佳方式是什么?
采纳答案by SeanR
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.
重新阅读您的描述,看起来您真正需要了解的是如何使用 WKWebView 重新实现 Javascript/Objective-C 桥。
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/
我自己刚刚完成了这个,按照http://tetontech.wordpress.com/2014/07/17/objective-c-wkwebview-to-javascript-and-back/ 上的教程和http:// 上的信息nshipster.com/wkwebkit/
WKWebView has a built-in way of communicating between Javascript and Objective-C/Swift: WKScriptMessageHandler
.
WKWebView 有一种内置的 Javascript 和 Objective-C/Swift 之间的通信方式:WKScriptMessageHandler
.
First, include the WebKit headers and WKScriptMessageHandler
protocol in your view controller's header:
首先,WKScriptMessageHandler
在你的视图控制器的头文件中包含 WebKit 头文件和协议:
#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.
初始化您的 时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];
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:
.
现在,实施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);
}
You're now ready to receive messages from Javascript. The function call you need to add to your Javascript is this:
您现在已准备好接收来自 Javascript 的消息。您需要添加到 Javascript 的函数调用是这样的:
window.webkit.messageHandlers.myApp.postMessage({"message":"Hello there"});
回答by SeanR
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):
我自己一直在寻找一个很好的解释,但没有找到。我在我的应用程序中使用了以下内容,一切似乎都有效(编辑:根据ccoroom 的评论更新):
UIWebViewDelegate - webView:shouldStartLoadWithRequest:navigationType:
WKNavigationDelegate - webView:decidePolicyForNavigationAction:decisionHandler:
Here's the other UIWebViewDelegate
methods:
这是其他UIWebViewDelegate
方法:
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.
编辑:实际上,我已经回答了您在标题中提出的问题(尽管我不再确信它webView:didCommitNavigation:
是在生命周期的完全相同点调用的),但是重新阅读您的描述,它看起来像您实际需要的了解如何使用 WKWebView 重新实现 Javascript/Objective-C 桥。所以看看我的另一个答案。
回答by robnasby
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.
要回答原始问题,webView:shouldStartLoadWithRequest:navigationType:
UIWebView 中的等效项是webView:decidePolicyForNavigationAction:decisionHandler:
WKWebView。这些方法在发出每个请求(包括初始请求)之前被调用,并提供允许/禁止它的能力。
回答by Benzi Heler
Just use the following method , it's a part of WKNavigationDelegate
只需使用以下方法,它是 WKNavigationDelegate 的一部分
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
NSString *url = [[request URL]absoluteString];
decisionHandler(WKNavigationActionPolicyAllow);
}
回答by u2603230
In Swiftyou can do something like this:
在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
}
}
And this is the link in web page:
这是网页中的链接:
<a href="http://action.is.needed/some-action">Hello world!</a>
回答by ingconti
for swift 4.2: (taking from Yifei He 何一非. )
for 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
}
}
回答by ramzi shadid
You can add Observer for your WKWebView
您可以为 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
不要忘记在 viewWillDisappear 中删除它
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[webView removeObserver:self forKeyPath:@"URL"];
}