JS与原生OC/Swift相互调用总结
JS-OC-Swift
JS和OC/Swift相互调用,主要总结了JS和OC交互的三种方式
1.使用UIWebView,利用JavaScriptCore实现
2.使用WKWebView,利用WKScriptMessageHandler实现
3.使用第三方框架WebViewJavascriptBridge实现
部分效果图

JavaScriptCore
JavaScriptCore介绍
JavaScriptCore框架是基于webkit中以C/C++实现的JavaScriptCore的一个包装,该框架让Objective-C和JavaScript代码直接的交互变得更加的简单方便,主要由下面几个类组成。
**1.JSContext **
JS执行的环境,同时也通过JSVirtualMachine管理着所有对象的生命周期,每个JSValue都和JSContext相关联并且强引用context。可以通过[webView valueForKeyPath:@”documentView.webView.mainFrame.javaScriptContext”]来从webview上获取相应的JSContext。
**2.JSValue **
JS对象在JSVirtualMachine中的一个强引用,其实就是Hybird对象。我们对JS的操作都是通过它。并且每个JSValue都是强引用一个context。同时,OC和JS对象之间的转换也是通过它。
**3.JSManagedValue **
JS和OC对象的内存管理辅助对象。由于JS内存管理是垃圾回收,并且JS中的对象都是强引用,而OC是引用计数。如果双方相互引用,势必会造成循环引用,而导致内存泄露。我们可以用JSManagedValue保存JSValue来避免。
**4.JSVirtualMachine **
JS运行的虚拟机,有独立的堆空间和垃圾回收机制。
**5.JSExport **
一个协议,如果JS对象想直接调用OC对象里面的方法和属性,那么这个OC对象只要实现这个JSExport协议就可以了。
在Swift中获取JS的context
context = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext
注入JS需要的对象,对象命名与html中使用的保持一致.self是遵守了JSExport协议,也可是其他遵守协议的对象。
context?.setObject(self, forKeyedSubscript: "OC" as NSCopying & NSObjectProtocol)
JS调用Swift的方法,在Swift中实现协议
@objc protocol JSDelegate :JSExport {
//包含参数的func,需要注意参数名对函数名称的影响
func showMessageToYou(_ message:String)
/*
对应html中“showAAndB”,此方法包含两个参数,需要在参数前加“_”
func showA(_ aString: String, andB: String)
func showAAndB(_ aString:String,_ bStr:String)
以上两个方法等同
*/
func showAAndB(_ aString:String,_ bStr:String)
func doActionCallBack()
}
Swift调用JS的方法
let jsStr = String(format:"callback('%@')",(textField?.text)!)
self.context?.evaluateScript(jsStr)
OC中可使用block和实现JSExport协议两种方式实现,代码实现:
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.context = context;
//注入JS需要的“OC”对象,该对象与html中的保持一致即可
self.context[@"OC"] = self;
WKScriptMessageHandler
初始化WKWebView后,添加供js调用oc/Swift的桥梁,这里的name对应WKScriptMessage中的name
webView.configuration.userContentController.add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)
遵守协议WKScriptMessageHandler,实现以下方法,可实现JS把消息发送给OC/Swift。
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
OC/Swift调用JS
let jsStr = String(format:"callback('%@')",(textField?.text)!)
self.webView.evaluateJavaScript(jsStr as String, completionHandler: { (result:Any?, error:Error?) in
print("error:",error as Any)
})
WebViewJavascriptBridge
WebViewJavascriptBridge是一个Objective-C与JavaScript进行消息互通的第三方库,可以很方便的实现OC和Javascript互调的功能。WebViewJavascriptBridge实现互调的过程也容易理解,就是在OC环境和Javascript环境各自保存一个相互调用的bridge对象,每一个调用之间都有id和callbackid来找到两个环境对应的处理。从Github上下载源码之后,可以看到核心类主要包含如下几个:
WebViewJavascriptBridge_JS:Javascript环境的Bridge初始化和处理。负责接收OC发给Javascript的消息,并且把Javascript环境的消息发送给OC。
WKWebViewJavascriptBridge/WebViewJavascriptBridge:主要负责OC环境的消息处理,并且把OC环境的消息发送给Javascript环境。
WebViewJavascriptBridgeBase:主要实现了OC环境的Bridge初始化和处理。
初始化WKWebViewJavascriptBridge
self.webViewBridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webView];
[self.webViewBridge setWebViewDelegate:self];
JS调用OC需要注册事件
[self.webViewBridge registerHandler:@"handlerName" handler:^(id data, WVJBResponseCallback responseCallback) {
//code
}];
OC调用JS
[self.webViewBridge callHandler:@"handlerName" data:@[textField.text] responseCallback:^(id responseData) {
NSLog(@"%@",responseData);
}];
html中需要放置以下代码
/*这段代码是固定的,必须要放到js中*/
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
/*与OC交互的所有JS方法都要放在此处注册,才能调用通过JS调用OC或者让OC调用这里的JS*/
setupWebViewJavascriptBridge(function(bridge) {
bridge.registerHandler('callback', function(data, responseCallback) {
callback(data);
responseCallback('js执行过了'+data);
})
})
项目结构
JS与原生OC/Swift相互调用总结
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
JS与原生OC/Swift相互调用总结的更多相关文章
- iOS下JS与原生OC互相调用(总结)
这是去年总结的一篇文章,也一并先放到这个目录下好了. iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式. JS调用原生OC篇 方 ...
- Swift与OC的相互调用
Swift经过四年的发展已经趋于成熟,是时候学一下了,感谢公司swift大佬的不吝赐教.心有所感记录一下,如有不足欢迎指正批评. 新建swift项目 新建Swift.OC类文件 可在新建OC文件时,建 ...
- js和vue方法的相互调用(iframe父子页面的方法相互调用)。
项目是前后端不分离的,模板引擎使用的JSP. 但是使用了Vue+ElementUI,这里列举一些常用的调用方式,有时候可能. 在js里调用vue方法 我们需要把方法注册到vue对象之外的页面,所以对与 ...
- iOS OC与swift相互调用
小哥("我"的自称)个人混编的时候喜欢先创建OC项目,然后在项目中创建swift类.这样有个好处就是桥文件可以自动创建的同事路径不需要我手动去写了,另外还有个目的就是现在小哥自我感 ...
- OC与swift相互调用
一.OC调用swift文件 二.swift调用OC文件 三.注意和总结 添加: 四.自定义桥接文件 一.OC调用swift文件 在OC项目中创建一个swift文件的时候,Xcode 会提示 需要创建一 ...
- iOS开发--JS调用原生OC篇
JS调用原生OC篇 方式一(反正我不用) 第一种方式是用JS发起一个假的URL请求,然后利用UIWebView的代理方法拦截这次请求,然后再做相应的处理. 我写了一个简单的HTML网页和一个btn点击 ...
- WebView中Js与Android本地函数的相互调用
介绍 随着Html5的普及,html在表现力上不一定比原生应用差,并且有很强的扩展兼容性,所以越来越多的应用是采用Html与Android原生混合开发模式实现. 既然要实现混合开发,那么Js与Andr ...
- Hybrid App开发模式中, IOS/Android 和 JavaScript相互调用方式
IOS:Objective-C 和 JavaScript 的相互调用 iOS7以前,iOS SDK 并没有原生提供 js 调用 native 代码的 API.但是 UIWebView 的一个 dele ...
- iOS下JS与原生的交互一
本篇主要讲的是UIWebView和JS的交互,在下一节会有wkWebView和JS交互的详解https://www.cnblogs.com/llhlj/p/9144110.html JS调用原生OC ...
随机推荐
- v4l2读取摄像头程序流程解析【转】
转自:https://my.oschina.net/u/1024767/blog/210801 v4l2 操作实际上就是 open() 设备, close() 设备,以及中间过程的 ioctl() 操 ...
- ios 最新系统bug与解决——微信公众号中弹出键盘再收起时,原虚拟键盘位点击事件无效
最近ios发布新版本系统12.1,随着部分用户的系统更新,一些问题也渐渐暴露出来... 公司用户反映微信公众号出现了点击无效的bug!!测试调查发现,只有iphonex.iphone6,ihpone7 ...
- Kubernetes DNS安装配置
#镜像在谷歌上需要FQ###################################下载kubernetes#DNS#cd kubernetes/cluster/addons/dns#修改tr ...
- 【linux高级程序设计】(第十一章)System V进程间通信 4
共享内存 共享内存主要用于实现进程间大量数据传输. 共享内存的数据结构定义: 系统对共享内存的限制: 共享内存与管道的对比: 可以看到,共享内存的优势: 1.共享内存只需复制2次,而管道需要4次 2. ...
- 纠正网上乱传的android调用Webservice方法。
1.写作背景: 笔者想实现android调用webservice,可是网上全是不管对与错乱转载的文章,结果不但不能解决问题,只会让人心烦,所以笔者决定将自己整理好的能用的android调用webser ...
- 关于ScrollView嵌套RecyclerView出现item显示不全的问题
最近使用ScrollView时,发现里面嵌套Listview显示不全,试过重写Listview的onMeasure(),并没有起作用.然后将ListView换成RecyclerView后,高度还是显示 ...
- (1)IIS
1.选择控制面板-程序和功能 2.点击左侧“打开或关闭Windows功能 3.internet信息服务下的文件夹全勾 4.安装完成后,选择管理工具 5.选择IIS管理器 6.显示如下
- (6)C#项目结构
一.项目下Properites文件夹 Properties文件夹 定义你程序集的属性 项目属性文件夹 一般只有一个 AssemblyInfo.cs 类文件,用于保存程序集的信息,如名称,版本等,这些信 ...
- request与response对象.
request与response对象. 1. request代表请求对象 response代表的响应对象. 学习它们我们可以操作http请求与响应. 2.request,response体系结构. 在 ...
- 个人博客 V0.0.3 版本 ...
早就想弄个人博客网站,一直拖到现在...事情总是忙不完的,想能力提升的快,只能挤时间多练多写了,Keep On Unsleeping 以后原创的笔记都会在自己的博客网站写,博客园和简书就用来转发文章了 ...