WKWebView下 oc 和 js 交互

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 
#import 

@interface WeakScriptMessageDelegate : NSObject
@property (nonatomic, assign) id scriptDelegate;
- (instancetype)initWithDelegate:(id)scriptDelegate;
@end

.m
@implementation WeakScriptMessageDelegate
- (instancetype)initWithDelegate:(id)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 交互)