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 的代码放在这里执行较好.
}
网友评论