UIWebView iOS 2.0 出现 ,WKWebView iOS 8.0出现
在微信中可以输入:switchweb
进行切换
但是发现个问题,现在输入之后切换不了了,微信版本6.6.5 系统版本11.2.6,有了解的请评论告知,感激不尽。
切换说明:微信公众平台技术文档
一、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,前端只需要写一套。
其实不管网页怎么写,都有对应的方法,只是方便不方便的问题,喜欢就好啦,无所谓。
正文 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];
}