iOS中JS与原生OC互相调用之问题总结二
来源:互联网 发布:樱井知香番号合集 编辑:程序博客网 时间:2024/06/05 07:18
今天继续给同学们讲解JS和OC的互相调用,今天给大家还是讲解WKWebView中的一些使用,和注意点,废话不多说直接上代码:
#pragma mark - WKWebView中的MessageHandler?
WKWebView初始化时,有一个参数叫configuration,它是WKWebViewConfiguration
类型的参数,而WKWebViewConfiguration
有一个属性叫userContentController
,它又是WKUserContentController
类型的参数。WKUserContentController
对象有一个方法
- addScriptMessageHandler:name:
我把这个功能简称为MessageHandler。
- addScriptMessageHandler:name:
有两个参数,第一个参数是userContentController的代理对象,第二个参数是JS里发送postMessage的对象(即你与前端JS定义好的方法名)。
#warning - 注意
所以要使用MessageHandler功能,就必须要实现WKScriptMessageHandler
协议。
#pragma mark - <WebKit/WebKit.h>API中对JS的使用方法介绍?
我们在该API的描述里可以看到在JS中的使用方法:
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
// 其中<name>,就是上面方法里的第二个参数'name';例:我们调用API的时候第二个参数填@"Share",那么在JS里就是: window.webkit.messageHandlers.Share.postMessage(<messageBody>)
// <messageBody>是一个键值对,键是body,值可以有多种类型的参数。
// 在'WKScriptMessageHandler'协议中,我们可以看到message是'WKScriptMessage'类型,有一个属性叫body
// 而注释里写明了body 的类型:Allowed types are NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull.
#pragma mark - 那么问题来了,如何使用MessageHandler呢?
1> 创建WKWebViewConfiguration
对象,配置各个API对应的MessageHandler,WKUserContentController
对象可以添加多个scriptMessageHandler。示例代码:
/**
* 创建一个WKWebViewConfiguration对象
*/
- (void)creatConfiguration
{
WKWebViewConfiguration *configuration = [[WKWebViewConfigurationalloc] init];
WKPreferences *preference = [[WKPreferencesalloc] init];// 对一个webView的属性设置
preference.javaScriptCanOpenWindowsAutomatically =YES;
configuration.preferences = preference;
}
#pragma mark - 一般在这里就设置整个view是webView
- (void)loadView
{
[superloadView];
self.view =self.webView;
}
#pragma mark - view即将出现的时候我们就可以监听
- (void)viewWillAppear:(BOOL)animated
{
[superviewWillAppear:animated];
// addScriptMessageHandler 很容易导致循环引用
// 控制器强引用了WKWebView,WKWebView copy(强引用了)configuration,configuration copy(强引用了)userContentController
// userContentController 强引用了 self(控制器)
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"ScanAction"];
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"Location"];
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"Share"];
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"Color"];
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"Pay"];
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"Shake"];
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"GoBack"];
[self.webView.configuration.userContentControlleraddScriptMessageHandler:selfname:@"PlaySound"];
}
#warning - 需要注意的是addScriptMessageHandler很容易引起循环引用,导致控制器无法被释放,所以需要加入以下这段
- (void)viewWillDisappear:(BOOL)animated
{
[superviewWillDisappear:animated];
// 因此这里要记得移除handlers
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"ScanAction"];
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"Location"];
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"Share"];
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"Color"];
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"Pay"];
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"Shake"];
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"GoBack"];
[self.webView.configuration.userContentControllerremoveScriptMessageHandlerForName:@"PlaySound"];
}
#pragma mark - 创建WKWebView?
- (void)viewDidLoad {
[superviewDidLoad];
// 0.创建WKWebView
[selfsetUpWebView];
// 1.创建WKWebViewConfiguration对象
[selfsetUpConfiguration];
}
/**
* 创建webView
*/
- (void)setUpWebView
{
self.webView = [[WKWebViewalloc] initWithFrame:self.view.frameconfiguration:nil];
NSString *urlStr = [[NSBundlemainBundle] pathForResource:@"test.html"ofType:nil];
NSURL *fileURL = [NSURLfileURLWithPath:urlStr];
[self.webViewloadFileURL:fileURL allowingReadAccessToURL:fileURL];
self.webView.navigationDelegate = self;
self.webView.UIDelegate =self;
[self.viewaddSubview:self.webView];
}
/**
* 创建一个WKWebViewConfiguration对象
*/
- (void)setUpConfiguration
{
WKWebViewConfiguration *configuration = [[WKWebViewConfigurationalloc] init];
WKPreferences *preference = [[WKPreferencesalloc] init];// 对一个webView的属性设置
preference.javaScriptCanOpenWindowsAutomatically =YES;
configuration.preferences = preference;
}
#pragma mark - 实现协议方法
#pragma mark - 我这里实现了两个协议<WKUIDelegate,WKScriptMessageHandler>,WKUIDelegate是因为我在JS中弹出了alert。WKScriptMessageHandler是因为我们要处理JS调用OC方法的请求。
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
// message.body -- Allowed types are NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull.
if ([message.nameisEqualToString:@"ScanAction"]) {
NSLog(@"扫一扫");
} elseif ([message.nameisEqualToString:@"Location"]) {
[selftest];
} elseif ([message.nameisEqualToString:@"Share"]) {
[selftest];
} elseif ([message.nameisEqualToString:@"Color"]) {
[selftest];
} elseif ([message.nameisEqualToString:@"Pay"]) {
[selftest];
} elseif ([message.nameisEqualToString:@"Shake"]) {
[selftest];
} elseif ([message.nameisEqualToString:@"GoBack"]) {
[selftest];
} elseif ([message.nameisEqualToString:@"PlaySound"]) {
[selftest];
}
}
- (void)test
{
}
#pragma mark - WKScriptMessage有两个关键属性name和body。因为我们给每一个OC方法取了一个name,那么我们就可以根据name来区分执行不同的方法。body中存着JS要给OC传的参数。关于参数body的解析,我就举一个body中放字典的例子.
/**
* @param tempDic tempDic来自message.body来自与JS传过来的参数
*/
- (void)shareWithParams:(NSDictionary *)tempDic
{
if (![tempDicisKindOfClass:[NSDictionaryclass]]) return;
// kvc取值
NSString *title = [tempDicobjectForKey:@"title"];
NSString *content = [tempDicobjectForKey:@"content"];
NSString *url = [tempDicobjectForKey:@"url"];
// 在这里执行分享的操作
#pragma mark - OC调用JS
// 将分享结果返回给js即:OC调用JS
NSString *jsStr = [NSStringstringWithFormat:@"shareResult('%@','%@','%@')",title,content,url];
[self.webViewevaluateJavaScript:jsStrcompletionHandler:^(id_Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];
}
#pragma mark - 那么这里总结用MessageHandler的好处
/*
* 1> 在JS中写起来简单,不用再用创建URL的方式那么麻烦了。
* 2> JS传递参数更方便。使用拦截URL的方式传递参数,只能把参数拼接在后面,如果遇到要传递的参数中有特殊字符,如&、=、?等,必须得转换,否则参数解析肯定会出错。
* 例如传递的url是这样的:
* http://www.baidu.com/share/openShare.htm?share_uuid=shdfxdfdsfsdf&name=1234567890
* 使用拦截URL的JS调用方式
* loadURL("firstClick://shareClick?title=分享的标题&content=分享的内容&url=链接地址&imagePath=图片地址"); }
* 将上面的url放入链接地址这里后,根本无法区分share_uuid是其他参数,还是url里附带的参数。
* 但是使用MessageHandler就可以避免特殊字符引起的问题。
*/
- iOS中JS与原生OC互相调用之问题总结二
- iOS中JS与原生OC互相调用之问题总结一
- iOS中JS与原生OC互相调用之JavaScriptCore
- iOS下JS与原生OC互相调用(总结)
- iOS下JS与原生OC互相调用(总结)
- iOS下JS与原生OC互相调用(总结)
- iOS下JS与原生OC互相调用(总结)
- iOS下JS与原生OC互相调用(总结)
- iOS下JS与原生OC互相调用
- iOS下JS与原生OC互相调用
- iOS下JS与原生OC互相调用
- iOS下JS与原生OC互相调用
- iOS下JS与原生OC互相调用
- iOS下JS与原生OC互相调用
- IOS中OC与JS互相调用
- JS与原生OC互相调用方法
- JS与原生OC互相调用
- [iOS js与oc原生互相调用] js调用oc的两种方式
- 使用VS2017的跨平台项目对muduo进行编译
- C语言初步-第24讲:if语句的嵌套(个人所得税计算器if语句版)
- 创建型模式之工厂模式
- Linux运维之网络文件系统NFS介绍与部署(CentOS 7.2版本)
- 读书笔记-07随需而变:网站的可扩展架构
- iOS中JS与原生OC互相调用之问题总结二
- Didn't find class "com.google.firebase.provider.FirebaseInitProvider"
- The study of Higher-order function in Python(20170913)
- c++ 插入迭代器
- 数据结构和算法--二叉树的实现
- 总结 2017.9.13
- Java连接MnogoDb数据库
- iOS 单例设计模式 单例写法
- 绝对大佬的模板%%%