代码地址如下:
http://www.demodashi.com/demo/12754.html

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相互调用总结

代码地址如下:
http://www.demodashi.com/demo/12754.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

JS与原生OC/Swift相互调用总结的更多相关文章

  1. iOS下JS与原生OC互相调用(总结)

    这是去年总结的一篇文章,也一并先放到这个目录下好了. iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式. JS调用原生OC篇 方 ...

  2. Swift与OC的相互调用

    Swift经过四年的发展已经趋于成熟,是时候学一下了,感谢公司swift大佬的不吝赐教.心有所感记录一下,如有不足欢迎指正批评. 新建swift项目 新建Swift.OC类文件 可在新建OC文件时,建 ...

  3. js和vue方法的相互调用(iframe父子页面的方法相互调用)。

    项目是前后端不分离的,模板引擎使用的JSP. 但是使用了Vue+ElementUI,这里列举一些常用的调用方式,有时候可能. 在js里调用vue方法 我们需要把方法注册到vue对象之外的页面,所以对与 ...

  4. iOS OC与swift相互调用

    小哥("我"的自称)个人混编的时候喜欢先创建OC项目,然后在项目中创建swift类.这样有个好处就是桥文件可以自动创建的同事路径不需要我手动去写了,另外还有个目的就是现在小哥自我感 ...

  5. OC与swift相互调用

    一.OC调用swift文件 二.swift调用OC文件 三.注意和总结 添加: 四.自定义桥接文件 一.OC调用swift文件 在OC项目中创建一个swift文件的时候,Xcode 会提示 需要创建一 ...

  6. iOS开发--JS调用原生OC篇

    JS调用原生OC篇 方式一(反正我不用) 第一种方式是用JS发起一个假的URL请求,然后利用UIWebView的代理方法拦截这次请求,然后再做相应的处理. 我写了一个简单的HTML网页和一个btn点击 ...

  7. WebView中Js与Android本地函数的相互调用

    介绍 随着Html5的普及,html在表现力上不一定比原生应用差,并且有很强的扩展兼容性,所以越来越多的应用是采用Html与Android原生混合开发模式实现. 既然要实现混合开发,那么Js与Andr ...

  8. Hybrid App开发模式中, IOS/Android 和 JavaScript相互调用方式

    IOS:Objective-C 和 JavaScript 的相互调用 iOS7以前,iOS SDK 并没有原生提供 js 调用 native 代码的 API.但是 UIWebView 的一个 dele ...

  9. iOS下JS与原生的交互一

    本篇主要讲的是UIWebView和JS的交互,在下一节会有wkWebView和JS交互的详解https://www.cnblogs.com/llhlj/p/9144110.html JS调用原生OC ...

随机推荐

  1. vs mfc 静态文本 改变字体大小

    VC的对话框字体设置对所有控件都有效,你不能单独地改变某个静态文本的字体.对于你的问题,需要首先用CreateFont来建立一个字体对象,然后调用控件的SetFont,就可以了. 例子: 1.改静态文 ...

  2. android hook 框架 libinject 如何实现so注入

    前面两篇 android hook 框架 libinject2 简介.编译.运行 android hook 框架 libinject2 如何实现so注入 实际运行并分析了 Android中的so注入( ...

  3. git的使用01

    直接下载安装git,这里就不演示了,如果安装成功,在桌面任意空白处单击鼠标右键,会多出两个选项 Git Gui Here和Git Bash Here,我们一般使用git bash here 右键之后点 ...

  4. java 调用可执行文件时,ProcessBuilder异常CreateProcess error=2

    java 调用其他应用程序时,可能在windows下没有问题,但是转到linux下,却会报这样那样的错误,比如有设计文件操作会报FileNotFoundException等等(如下代码): Proce ...

  5. 使用windos电脑模拟搭建集群(四)web环境 linux+nginx+jdk+tomcat

    1.使用ansible的playbook自动安装两台web主机的nginx 1.配置模块 主机清单 2.创建 playbook目录并编写安装nginx的playbook mkdir -p playbo ...

  6. Netty源码学习(六)ChannelPipeline

    0. ChannelPipeline简介 ChannelPipeline = Channel + Pipeline,也就是说首先它与Channel绑定,然后它是起到类似于管道的作用:字节流在Chann ...

  7. POJ 3225.Help with Intervals-线段树(成段替换、区间异或、简单hash)

    POJ3225.Help with Intervals 这个题就是对区间的各种操作,感觉这道题写的一点意思都没有,写到后面都不想写了,而且更神奇的是,自己的编译器连结果都输不出来,但是交上就过了,也是 ...

  8. 洛谷 P3378 【模板】堆

    如题,初始小根堆为空,我们需要支持以下3种操作: 操作1: 1 x 表示将x插入到堆中 操作2: 2 输出该小根堆内的最小数 操作3: 3 删除该小根堆内的最小数 输入输出格式 输入格式: 第一行包含 ...

  9. Leave It Behind and Carry On ---- 高一下期末考反思 [补档]

    背景 这个学期的前\(\frac{3}{4}\), 我都是在停课集训中度过的, 先是GDKOI, 再是北京集训, 最后是GDOI, 结果GDOI还没进day3就滚粗了. 学校的内容是考完GDOI后回学 ...

  10. hdu 1506 Largest Rectangle in a Histogram 构造

    题目链接:HDU - 1506 A histogram is a polygon composed of a sequence of rectangles aligned at a common ba ...