wkwebview

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 )scriptMessageHandler name:(NSString *)name;

//回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

self作为delegate后,self并没有释放,dealloc方法并没有执行;
思路是另外创建一个代理对象,然后通过代理对象回调指定的self
解决方法为新建一个继承NSObject的子类,并实现WKScriptMessageHandler的协议;

@interface LWWeakScriptMessageDelegate ()

@property (nonatomic, weak) id scriptDelegate;

@end

@implementation LWWeakScriptMessageDelegate

- (instancetype)initWithDelegate:(id)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 )scriptMessageHandler name:(NSString *)name
// 调用了该方法必须要调用
- (void)removeScriptMessageHandlerForName:(NSString *)name;
// 二者必须要同时存在,一一对应 dealloc中调用

由于使用了addScriptMessageHandler方式监听消息,就必须要实现WKScriptMessageHandler代理,并在里面进行name的判断,不能做到一一对应,所以重新定义了一个继承WKWebViewLWWKWebView对消息监听和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

你可能感兴趣的:(wkwebview)