1 JS与OC交互
UIWebViewDelegate
比较简单,利用 UIWebViewDelegate 的代理方法进行拦截;
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
}
JavaScriptCore
苹果在iOS7中加入了JavaScriptCore框架,让OC与JS代码的交互变得简单。
WebViewJavaScriptBridge
一个OC与JS进行消息互通的第三方库,主要是使用Block回调传递消息。
2 JavaScriptCore
2.1 JavaScriptCore
基于 webkit 中的 JavaScriptCore 的一个包装,在旧版的开发中,开发者会自行将 为 webkit 的库引入项目中编译使用,苹果在iOS7中把它当成一个标准库。
引入 JavaScriptCore ,头文件可见5个文件。
- JSContext
- JSValue
- JSVirtualMachine
- JSManagedValue
- JSExport
2.2 JSContext
JSContext 上下文,是JS的执行环境,并通过 JSVirtualMachine 来管理所有对象的生命周期。
JSContext *context = [[JSContext alloc] init];
[context evaluateScript:@"var num = 5 + 5"];
[context evaluateScript:@"var triple = function(value) { return value * 3 }"];
2.3 JSValue
一个 JSValue 实例是一个 JavaScript 值的引用,可以使用 JSValue 类在JS与OC之间进行一些基本数值的转换,这样就可以在原生与 JavaScript 代码之间传递数据。提供了创建、读取转换、判断等方法。
JSValue *tripleNum = [context evaluateScript:@"triple(num)"];
JS与OC对象相关类型的转换,如下:
Objective-C type | JavaScript type |
---|---|
nil | undefined |
NSNull | null |
NSString | string |
NSNumber | number/boolean |
NSDictionary | object |
NSArray | Array |
NSDate | Date |
NSBlock | Function |
id | object |
Class | object |
2.4 JSExport
提供一个将OC中的类、实例方法和属性等导出为 JavaScript 函数的方法。
默认情况下,OC类的所有方法和属性都不会被暴露给JavaScript,所以必须要选择要暴露的方法和属性。对于类遵守的任意协议,如果该协议包含了JSExport协议,则JavaScriptCore就会认为这个该协议中包含的方法和属性列表是暴露给JavaScript的。这个时候,我们才能在JavaScript调用OC类的exported的方法和属性。
(参考Demo,实现OC与JS之间的通信的方式)
2.5 JSVirtualMachine
概念:代表着JS执行的环境。
每一个JSContext对象都属于一个虚拟机。每一个虚拟机都能够包含多个context,并且允许在两个context之间传递JSValue对象。然而,每一个虚拟机又是独特的,我们不能够传递一个value从一个虚拟机的context到另外一个虚拟机的context。
作用:
支持 JS 并发执行;
为了执行JavaScript多线程的并发,为每一个线程使用一个独立的 JSVirtualMachine。
为 JS 与 OC 交互管理内存。
JS 的内存管理是垃圾回收机制,JS 中的对象都是强引用。而OC采用的是引用计数。如果两者相互引用,就可能会出现循环引用的情况,导致内存泄露。
(比如,在一个方法中创建了一个临时的Objective-C对象,然后将其加入到JSContext放在JavaScript中的变量中被使用。因为JavaScript中的变量有引用所以不会被释放回收,但是Objective-C上的对象可能在方法调用结束后,引用计数变0而被回收内存,因此JavaScript层面也会造成错误访问)
// 建立弱引用关系(使JS在运行时得知OC对象)
- (void)addManagedReference:(id)object withOwner:(id)owner;
// 手动移除之间的联系
- (void)removeManagedReference:(id)object withOwner:(id)owner;
2.6 JSManagedValue
JSValue的封装,作为JS与OC对象交互的内存管理辅助对象。
一个 JSManagedValue 对象是对本身一个 JSValue 的ARC弱引用,避免循环引用。
+ (JSManagedValue *)managedValueWithValue:(JSValue *)value;
解决内存泄露问题:
打破循环,就需要在OC上对需要保存的JS对象封装为 JSManagedValue,并把JSManagedValue 交给 JSVirtualMachine 来管理。