WKWebView之OC与 JS 交互

WKWebView 是 iOS8 推出的组件, 相比 UIWebView 而言, 很大程度上解决了内存占用量巨大的问题. 在这里主要说一些通过 WKWebView 来实现 Objective-C 和 JavaScript 的交互.

一、初始化 WKWebView 及其配置

//导入#import  

@interface WKWebViewViewController ()
{
    WKUserContentController *_userContentController;
}
@property(nonatomic,strong) WKWebView *wkWebView;
@property(nonatomic,strong) UIProgressView *progressView;

@end
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
    
    //注册供js调用的方法
    _userContentController =[[WKUserContentController alloc]init];
    _userContentController =[[WKUserContentController alloc]init];
    [_userContentController addScriptMessageHandler:self  name:@"buttonAction"];
    [_userContentController addScriptMessageHandler:self  name:@"alertAction"];
    [_userContentController addScriptMessageHandler:self  name:@"changeNav"];
    [_userContentController addScriptMessageHandler:self  name:@"closeWeb"];
    [_userContentController addScriptMessageHandler:self  name:@"sendDic"];
    
    configuration.userContentController = _userContentController;
    
    configuration.preferences.javaScriptEnabled = YES;
    
    //初始化 WKWebView
    WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, DEVICE_WIDTH, DEVICE_HEIGHT) configuration:configuration];
    
    webView.backgroundColor = [UIColor clearColor];
    webView.UIDelegate = self;
    webView.navigationDelegate = self;
    webView.allowsBackForwardNavigationGestures =YES;//打开网页间的 滑动返回
    webView.allowsLinkPreview = YES;//允许预览链接
    
    [self.view addSubview:webView];

加载 URL

//网络h5
//    NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
//    [webView loadRequest:[NSURLRequest requestWithURL:url]];
    
    //加载本地H5
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];
    NSString * htmlPath = [[NSBundle mainBundle] pathForResource:@"JSDemo"
                                                          ofType:@"html"];
    NSString * htmlCont = [NSString stringWithContentsOfFile:htmlPath
                                                    encoding:NSUTF8StringEncoding
                                                       error:nil];
    [webView loadHTMLString:htmlCont baseURL:baseURL];

同时, 可以在初始化方法中, 添加对网页加载进度的监听, 设置相应的进度条:

//初始化进度条监听
[self initProgressView];
//注册 KVO 监听 拿到加载进度
[webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
#pragma mark - 初始化进度条
- (void)initProgressView {
    
    UIProgressView *progressView =[[UIProgressView alloc]initWithFrame:CGRectMake(0,64, DEVICE_WIDTH, 10)];
    progressView.tintColor = [UIColor blueColor];
    progressView.trackTintColor = [UIColor whiteColor];
    [self.view addSubview:progressView];
    
    //
    self.progressView = progressView;
}
#pragma mark - KVO 监听进度条
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    
    if([keyPath isEqualToString:@"estimatedProgress"]){
        
        _progressView.hidden = NO;
        CGFloat progress = [change[@"new"] floatValue];
        [_progressView setProgress:progress];
        if(progress == 1.0){
            
            _progressView.hidden =YES;
        }
    }
}

二、实现 OC 月 JS 交互的关键方法

#pragma mark -  实现注册的供js调用的oc方法 关键
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    
    if(message.name == nil || [message.name isEqualToString:@""]){
        
        return;
    }
    
    //message.body : js 传过来值
    NSLog(@"message.body ==%@",message.body);
    
    //message.name  js发送的方法名称
    //每个方法传不传参数, 传什么类型的参数, 需要和后台确定
    if([message.name  isEqualToString:@"buttonAction"]){
        
        //获取 js 传来的参数
        NSString *body = [message.body objectForKey:@"body"];
        
        [self logNumber:body];
        [self uilabel:body];
        NSLog(@"%@",body);
    }else if ([message.name isEqualToString:@"alertAction"]){
        
        NSString *body = [message.body objectForKey:@"body"];
        
        [self showAlert:body];
    }else if ([message.name isEqualToString:@"changeNav"]){
        
        NSString * info =[message.body objectForKey:@"body"];
        
        NSArray * arr =[info componentsSeparatedByString:@"&"];
        [self changeNavBarColor:arr[0] title:arr[1]];
        
        NSLog(@"js dic====%@",info);
    }else if ([message.name isEqualToString:@"closeWeb"]){
        
        [self closeWeb];
    }else if ([message.name isEqualToString:@"sendDic"]){
        
        NSDictionary *body = [message.body objectForKey:@"body"];
        
        [self showAlert:[NSString stringWithFormat:@"%@ + %@",body[@"a"],body[@"b"]]];
    }
}
#pragma mark - 实现注册的供 JS 调用的 OC方法
- (void)closeWeb {
    
    [self.navigationController popViewControllerAnimated:YES];
}
-(void)relaodWeb {
    
    [_wkWebView reload];
}
- (void)showAlert:(NSString * )msg {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"提示" message:msg delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    });
}

三、我们需要在页面关闭的时候, 移除注册的方法

#pragma mark - 注册的方法要在view dealloc前 remove 否则 不走 dealloc 
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    [_userContentController removeScriptMessageHandlerForName:@"buttonAction"];
    [_userContentController removeScriptMessageHandlerForName:@"alertAction"];
    [_userContentController removeScriptMessageHandlerForName:@"changeNav"];
    [_userContentController removeScriptMessageHandlerForName:@"closeWeb"];
    [_userContentController removeScriptMessageHandlerForName:@"sendDic"];
}
- (void)dealloc {
    
    //移除 KVO 监听
    [_wkWebView removeObserver:self forKeyPath:@"estimatedProgress"];
    
    NSLog(@"wkWebview dealloc");
}

DEMO 下载

你可能感兴趣的:(WKWebView之OC与 JS 交互)