美文网首页
WKWebView下 oc 和 js 交互

WKWebView下 oc 和 js 交互

作者: 楼上那只猫 | 来源:发表于2018-01-31 16:06 被阅读36次

    1. js 调用 oc

    1.初始化 wkwebview

    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    self.wb = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) configuration:config];
    [self.wb.configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];   //允许跨域请求
     [self.view addSubview:_wb];
    _wb.navigationDelegate = self;
    

    2.注册

    下面是一段 js 代码,假设是点击一个 button 触发的方法

    function toLink( ){
          //下面这句代码是关键,要想 js 能调用 oc,必须写下面这句,其中'callUs'就是注册时,原生代码中要保持一致的名字, null 为传递的参数,也可以传其他值.
          window.webkit.messageHandlers.callUs.postMessage(null)
     }
    
    //在 oc 代码中,需要注册这个名字(callUs)
    [self.wb.configuration.userContentController addScriptMessageHandler:self name:@"callUs"];
    

    注意,这里有个问题会造成 self 不会释放,为了解决该问题,可以用下面的方式注册

    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        [self.wb.configuration.userContentController addScriptMessageHandler:self name:@"callUs"];
        [self.wb.configuration.userContentController addScriptMessageHandler:self name:@"showDetail"];
    }
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        [self.wb.configuration.userContentController removeScriptMessageHandlerForName:@"callUs"];
        [self.wb.configuration.userContentController removeScriptMessageHandlerForName:@"showDetail"];
    }
    

    还有一种方法就是指定另一个类作为代理方法

    .h
    #import <Foundation/Foundation.h>
    #import <WebKit/WebKit.h>
    
    @interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>
    @property (nonatomic, assign) id<WKScriptMessageHandler> scriptDelegate;
    - (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;
    @end
    
    .m
    @implementation WeakScriptMessageDelegate
    - (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
    
    

    3.在代理方法中响应 js 方法

    //该代理方法会在执行 js 方法时被调用
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
        if ([message.name isEqualToString:@"callUs"]) {    //这里可以判断调用的 js 方法是否和注册的一样
            [self alertViewWithPhone:@"85225010199"];
        } else if ([message.name isEqualToString:@"showDetail"]) {
            NSString * fundId = message.body;
            JFFundDetailController * vc = [[JFFundDetailController alloc] init];
            vc.fundId = fundId;
            [self.navigationController pushViewController:vc animated:YES];
        }
    }
    

    然后在加载 h5的页面中可以这样写.(可以在 viewDidLoad 方法中直接写)

    [self.wb.configuration.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"callUs"];
    [self.wb.configuration.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"showDetail"];
    

    同时不要忘了在 dealloc 方法中,移除 handler

    - (void)dealloc {
        [_wb.configuration.userContentController removeScriptMessageHandlerForName:@"callUs"];
        [_wb.configuration.userContentController removeScriptMessageHandlerForName:@"showDetail"];
    }
    

    2. oc调用 js

    //resArr 是 oc 中得到的一个数组,转为 json 字符串后,调用 js 中一个名字为'fundList'的方法,并且将 json 字符串作为参数传入.
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self.resArr options:NSJSONWritingPrettyPrinted error:nil];
    NSString * jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSString * jsFunc = [NSString stringWithFormat:@"fundList(%@)", jsonString];
    [self.wb evaluateJavaScript:jsFunc completionHandler:^(id _Nullable response, NSError * _Nullable error) {
            //response 可以接受 js 方法的返回值.            
    }];
    

    上面的代码,最好是在 h5加载完成后执行

    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
        //oc调用 js 的代码放在这里执行较好.
    }
    

    相关文章

      网友评论

          本文标题:WKWebView下 oc 和 js 交互

          本文链接:https://www.haomeiwen.com/subject/ihxlzxtx.html