wkwebview
2017-07-31 本文已影响0人
dl_wj15
WKWebView 是苹果在 WWDC 2014 上推出的新一代 webView 组件,用以替代 UIKit 中笨重难用、内存泄漏的 UIWebView。WKWebView拥有60fps滚动刷新率、和 safari 相同的 JavaScript 引擎等优势。
一、创建方法
WKWebView有两种创建方式
- 直接创建
WKWebView *webView = [[WKWebView alloc] init];
- 添加
WKWebViewConfiguration
用来监听消息回调
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.selectionGranularity = WKSelectionGranularityDynamic;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
二、加载网页
WKWebView
加载HTML代码和网页基本和UIWebview
一样
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
[self.view addSubview:webView];
二、加载的状态回调 (WKNavigationDelegate)
加载过程调用
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
页面跳转的代理方法:
// 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
// 在收到响应后,决定是否跳转,请求已经开始
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
// 在发送请求之前,决定是否跳转,请求尚未开始
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
三、JS调用App注册过的方法(iOS)
//scriptMessageHandler是代理回调,JS调用name方法后,OC会调用scriptMessageHandler指定的对象。
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
//回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
把self
作为delegate
后,self
并没有释放,dealloc
方法并没有执行;
思路是另外创建一个代理对象,然后通过代理对象回调指定的self
解决方法为新建一个继承NSObject
的子类,并实现WKScriptMessageHandler
的协议;
@interface LWWeakScriptMessageDelegate ()
@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;
@end
@implementation LWWeakScriptMessageDelegate
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate
{
if (self = [super init]) {
_scriptDelegate = scriptDelegate;
}
return self;
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
[self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}
}
使用方式
[self.webView.configuration.userContentController addScriptMessageHandler:[[LWWeakScriptMessageDelegate alloc] initWithDelegate:self] name:messageName];
到此可以释放self
但是并不能释放WeakScriptMessageDelegate
注意:
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name
// 调用了该方法必须要调用
- (void)removeScriptMessageHandlerForName:(NSString *)name;
// 二者必须要同时存在,一一对应 dealloc中调用
由于使用了addScriptMessageHandler
方式监听消息,就必须要实现WKScriptMessageHandler
代理,并在里面进行name
的判断,不能做到一一对应,所以重新定义了一个继承WKWebView
的LWWKWebView
对消息监听和OC调JS进行封装
// 添加消息监听
- (void)lw_addScriptMessageWithName:(NSString *)messageName completionHandler:(void (^) (id))completionHandler
{
[self.configuration.userContentController addScriptMessageHandler:[[LWWeakScriptMessageDelegate alloc] initWithDelegate:self] name:messageName];
if (completionHandler) {
[self.scriptMessageHandler setObject:completionHandler forKey:messageName];
}
}
// 消息监听回调,对接收的参数进行JSON解析
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
void (^messageHandler) (id) = [_scriptMessageHandler objectForKey:message.name];
if (messageHandler) {
id body;
if (message.body) {
body = [NSJSONSerialization JSONObjectWithData:[message.body dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:NULL];
}
messageHandler(body);
}
}
实际的使用,减少if else
的判断和出错率
[self.lw_webView lw_addScriptMessageWithName:@"onReceiveValue" completionHandler:^(id responseObject) {
NSLog(@"responseObject %@", responseObject);
}];
后续将继续研究WKWebView
cookie的使用,请继续关注小白
最后献上demo喜欢的记得点个☆star