iOSiOS 进阶

iOS WKWebView & JS

2018-03-03  本文已影响159人  _YZG_

UIWebView iOS 2.0 出现 ,WKWebView iOS 8.0出现
在微信中可以输入:switchweb进行切换

但是发现个问题,现在输入之后切换不了了,微信版本6.6.5 系统版本11.2.6,有了解的请评论告知,感激不尽。

切换说明:微信公众平台技术文档

:switchweb

一、UIWebView&WKWebView选择&比较

WKWebView是苹果在WWDC2014发布会中发布的iOS 8的时候公布的WebKit时候使用的新型的H5容器。它与UIWebView相比较,拥有更快的加载速度和性能,更低的内存占用。将UIWebViewDelegate和UIWebView重构成了14个类,3个协议,可以让开发者进行更加细致的配置。

我的观点哈,能用WKWebView就用,除非一些特殊情况,如要适配iOS 7等,WKWebView的请求不能被NSURLProtocol截获等等。但是可以通过其他方式,如https://github.com/WildDylan/WKWebViewWithURLProtocol是通过私有API让WKWebView可以支持NSURLProtocol的

二、关于JS交互

使用https://github.com/marcuswestin/WebViewJavascriptBridge支持UIWebView与WKWebView,并且在Android有一套对应的https://github.com/lzyzsd/JsBridge,前端只需要写一套。

WebViewJavascriptBridge使用链接

其实不管网页怎么写,都有对应的方法,只是方便不方便的问题,喜欢就好啦,无所谓。

正文 WKWebView & JS

三、动态加载并运行JS代码

// 图片缩放的js代码
NSString *js = @"js code";
// 根据JS字符串初始化WKUserScript对象
WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
// 根据生成的WKUserScript对象,初始化WKWebViewConfiguration
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
[config.userContentController addUserScript:script];
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
[_webView loadHTMLString:@"html code"baseURL:nil];
[self.view addSubview:_webView];

四、OC 执行 JS 代码

//javaScriptString是JS方法名,completionHandler是异步回调block
[self.webView evaluateJavaScript:javaScriptString completionHandler:completionHandler];

五、JS 执行 OC 代码

JS在调用OC方法的时候用下面的方式

window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

例:

// 没有参数也要写null否则代理方法不会执行
window.webkit.messageHandlers.closeMe.postMessage(null);

在iOS端

//OC注册供JS调用的方法
[[self.webView configuration].userContentController addScriptMessageHandler:self name:@"closeMe"];


WKScriptMessageHandler 代理
//OC在JS调用方法做的处理
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"JS 调用了 %@ 方法,传回参数 %@",message.name,message.body);
}

六、内存泄露解决方案

思路是另外创建一个代理对象,然后通过代理对象回调指定的self
具体如下

@interface HPWeakScriptMessageDelegate : NSObject 
@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@end

@implementation HPWeakScriptMessageDelegate
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate
{
    self = [super init];
    if (self) {
        _scriptDelegate = scriptDelegate;
    }
    return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}


@end

使用HPWeakScriptMessageDelegate

//设置addScriptMessageHandler与name.并且设置<WKScriptMessageHandler>协议与协议方法
[[self.wkWebView configuration].userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"对象名"];

销毁

- (void)dealloc {
    ...
    [[self.webView configuration].userContentController removeScriptMessageHandlerForName:@"对象名"];
    ...
}

七、WKWebView Alert无法弹出问题

实现WKUIDelegate

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
}
上一篇 下一篇

猜你喜欢

热点阅读