苹果下发最后通牒,如果您的 app 仍在使用已弃用的 UIWebView API 嵌入网络内容,我们强烈建议您尽快更新为 WKWebView 以提升安全性和稳定性。WKWebView 可将网页处理限制在 app 的网页视图中,从而确保不安全的网站内容不会影响到 app 的其他部分。此外,iOS、macOS 和 Mac Catalyst 均支持 WKWebView。
2020 年 4 月起 App Store 将不再接受使用 UIWebView 的新 app,2020 年 12 月起将不再接受使用 UIWebView 的 app 更新。
虽然苹果声明 2020 年 12 月起将不再接受使用 UIWebView 的 app 更新,但截止目前 2021年 11 月,苹果依然允许应用开发者更新基于 UIWebView 的 app。
关于iOS15
自 iOS15 正式版发布以来,发现在 iOS15 以下正常使用的桥接功能,在 iOS15 系统出现 H5 找不到桥接方法的问题,请尽快适配 WKWebView。
前置条件
1、导入WebKit.framework
2、声明WKWebView
@interface ViewController ()
@property (nonatomic, strong) WKWebView * webView;
@end
3、初始化
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *userController = [[WKUserContentController alloc] init];
configuration.userContentController = userController;
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kURL]];
[self.webView loadRequest:request];
[self.view addSubview:self.webView];
}
JS调用OC原生方法(无返回参数)
前端在js文件中实现
1、这里要注意 messageHandlers 后面跟着的 deviceInfo 要与原生的定义的一致,即 deviceInfo 为 H5 与原生的桥接方法。
2、如有多个参数,请使用 json 形式传递。
//有参数
window.webkit.messageHandlers.deviceInfo.postMessage({
"body": "buttonActionMessage"
});
//无参数
window.webkit.messageHandlers.deviceInfo.postMessage("");
iOS 实现 WKScriptMessageHandler 协议
@interface ViewController ()<WKScriptMessageHandler>
@property (nonatomic, strong) WKWebView * webView;
@end
注册桥接方法
注意:不要重复注册,否则会Crash
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"deviceInfo"];
}
注销桥接方法
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"deviceInfo"];
}
iOS 实现 WKScriptMessageHandler 协议方法
message.body 就是前端传来的参数
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"deviceInfo"]) {
NSString *deviceInfoStr = message.body;
NSLog(@"deviceInfo:%@", deviceInfoStr);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"JS调用的OC回调方法" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleCancel handler:nil];
;
[self presentViewController:alert animated:YES completion:nil];
}
}
JS调用OC原生方法(有返回参数)
JS 调用 OC 原生方法后,需要原生处理完成后 return 个结果给 JS,例如: JS 获取原生用户信息
前端在js文件中实现
1、约定 text 参数为给原生桥接的方法名
2、约定 defaultText 参数为给原生的参数,如有多个,转成json字符串的形式传递
prompt(text, defaultText)
iOS 实现 WKUIDelegate 协议
@interface ViewController ()<WKUIDelegate, WKScriptMessageHandler>
@property (nonatomic, strong) WKWebView * webView;
@end
iOS 实现 WKUIDelegate 协议方法
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {
if ([prompt isEqualToString:@"text"]) {
// text 为约定好的桥接方法名
// 如果需要返回前端对象,需要转成json字符串形式
NSString * str = @"Hello world";
completionHandler(str);
}
}
OC调用JS方法
1、实现WKNavigationDelegate协议
@interface ViewController ()
@property (nonatomic, strong) WKWebView * webView;
@end
2、实现WKNavigationDelegate协议的- webView: didFinishNavigation:方法
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
}
3、OC调用JS方法
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[webView evaluateJavaScript:@"deviceInfo('8.3')" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"ok");
}];
}
其中 deviceInfo(‘8.3’) 为前端给出的 JS 方法名 8.3 是需要传给前端的参数,如果需要传递多个参数,请使用 json 字符串。
4、注意事项
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
一定要在网页加载完成后调用,否则报错
图片出处不详,请作者看到与我联系,侵删