我爱编程

iOS 与 JS 交互

2016-05-19  本文已影响524人  胖次有毒zZ

推荐使用WKWebView

WKWebView 是苹果在 iOS 8 中引入的新组件,目的是给出一个新的高性能的 Web View 解决方案,摆脱过去 UIWebView 的老旧笨重特别是内存占用量巨大的问题。苹果将 UIWebViewDelegate 与 UIWebView 重构成了 14 个类和 3 个协议,引入了不少新的功能和接口。

WKWebView准备工作

<pre><code>#import <WebKit/WebKit.h>

@interface ViewController () <WKScriptMessageHandler, WKNavigationDelegate, WKUIDelegate>

@end
</pre></code>

在创建WKWebView之前,我们先做配置操作

这边就需要用到WKWebViewConfiguration
<pre><code> WKWebViewConfiguration *config =[[WKWebViewConfiguration alloc] init];
</pre></code>

交互需要利用WKUserContentController

这个类是用来给JS注入对象的,对象是和网页端一起约定好的。
config.userContentController = [[WKUserContentController alloc] init];
例如我们现在约定使用sendInfoModel这个对象,那么:

下面利用上面的WKWebViewConfiguration *config配置构造器来创建KWWebView

<pre><code>
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];

NSURL *path = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];

[self.webView loadRequest:[NSURLRequest requestWithURL:path]];

[self.view addSubview:self.webView];
</pre></code>

WKWebView在请求开始前会调用下面这个代理方法:

-webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler

<pre><code>- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler

{

NSString *hostname = navigationAction.request.URL.host.lowercaseString;

if (navigationAction.navigationType == WKNavigationTypeLinkActivated
&& ![hostname containsString:@".lanou.com"])

{
// 对于跨域,需要手动跳转
[[UIApplication sharedApplication] openURL:navigationAction.request.URL];

// 不允许web内跳转

decisionHandler(WKNavigationActionPolicyCancel);

} else

{

//允许web内跳转

self.progressView.alpha = 1.0;//(显示进度条)

decisionHandler(WKNavigationActionPolicyAllow);
}

}
</pre></code>

KWWebView完成响应

<pre><code>-(void)webView:(WKWebView *)webView
decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler

{
//允许响应

decisionHandler(WKNavigationResponsePolicyAllow);

//若为不允许响应,那么web内容就传不过来

}
</pre></code>

针对HTTPS协议的链接,加载时都会触发以下方法来验证证书(操作与使用AFN进行HTTPS验证证书一样)

<pre><code>-(void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:
(void (^)(NSURLSessionAuthChallengeDisposition disposition,
NSURLCredential *__nullable credential))completionHandler

{

//如不需要验证传默认的就可以

completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
</pre></code>

WKUIDelegate

与JS原生的alert,confirm,prompt进行交互:

</pre></code>
OC中: 当JS调用alert时会触发此方法
<pre><code>- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message
initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:@"JS调用alert" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style: UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}]];

[self presentViewController:alert animated:YES completion:NULL];
NSLog(@"%@", message);
}
</pre></code>

与alert相似

 JS中:

<pre><code>
function callJsConfirm() {
if (confirm('confirm', 'Objective-C call js to show confirm')) {
document.getElementById('jsParamFuncSpan').innerHTML
= 'true';
// sendInfoModel是我们所注入的对象
window.webkit.messageHandlers.sendInfoModel.postMessage({body: '我是JS里面的内容'});//传值
} else {
document.getElementById('jsParamFuncSpan').innerHTML
= 'false';
}

}

function callJsInput() {
  var response = prompt('Hello', '请输入你的名字:');
  document.getElementById('jsParamFuncSpan').innerHTML = response;
  
   // sendInfoModel是我们所注入的对象
  window.webkit.messageHandlers.sendInfoModel.postMessage({body: response});
}

</pre></code>

OC中:

<pre><code>- (void)webView:(WKWebView *)webView
runJavaScriptConfirmPanelWithMessage:(NSString *)message
initiatedByFrame:(WKFrameInfo *)frame
completionHandler:(void (^)(BOOL result))completionHandler

{

UIAlertController *alert = [UIAlertController alertControllerWithTitle:
@"confirm" message:@"JS调用confirm"
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action){
completionHandler(YES);
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"取消"
style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler(NO);
}]];
[self presentViewController:alert animated:YES completion:NULL];
NSLog(@"%@", message);

}

-(void)webView:(WKWebView *)webView
runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt
defaultText:(nullable NSString *)defaultText
initiatedByFrame:(WKFrameInfo *)frame
completionHandler:(void (^)(NSString * __nullable result))completionHandler

{

NSLog(@"%@", prompt);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:
@"textinput" message:@"JS调用输入框"
preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.textColor = [UIColor redColor];
}];
[alert addAction:[UIAlertAction actionWithTitle:@"确定"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler([[alert.textFields lastObject] text]);
}]];

[self presentViewController:alert animated:YES completion:NULL];

}
</pre></code>

上一篇 下一篇

猜你喜欢

热点阅读