JavaScriptCore(2)

来源:互联网 发布:fzltchjw gb1 0 mac 编辑:程序博客网 时间:2024/05/01 23:56

异常处理

Objective-C的异常会在运行时被Xcode捕获,而在JSContext中执行的JavaScript如果出现异常,只会被JSContext捕获并存储在exception属性上,而不会向外抛出。时时刻刻检查JSContext对象的exception是否不为nil显然是不合适,更合理的方式是给JSContext对象设置exceptionHandler,它接受的是^(JSContext *context, JSValue *exceptionValue)形式的Block。其默认值就是将传入的exceptionValue赋给传入的contextexception属性:

1     ^(JSContext *context, JSValue *exceptionValue) {2         context.exception = exceptionValue;3     };

我们也可以给exceptionHandler赋予新的Block以便在JavaScript运行发生异常的时候我们可以立即知道:

复制代码
 1     JSContext *context = [[JSContext alloc] init]; 2     context.exceptionHandler = ^(JSContext *con, JSValue *exception) { 3         NSLog(@"%@", exception); 4         con.exception = exception; 5     }; 6       7     [context evaluateScript:@"ider.zheng = 21"]; 8       9     //Output:10     // ReferenceError: Can't find variable: ider
复制代码

 

使用Block的注意事项

从之前的例子和介绍应该有体会到Block在JavaScriptCore中起到的强大作用,它在JavaScript和Objective-C之间的转换 建立起更多的桥梁,让互通更方便。但是要注意的是无论是把Block传给JSContext对象让其变成JavaScript方法,还是把它赋给exceptionHandler属性,在Block内都不要直接使用其外部定义的JSContext对象或者JSValue,应该将其当做参数传入到Block中,或者通过JSContext的类方法+ (JSContext *)currentContext;来获得。否则会造成循环引用使得内存无法被正确释放。


比如上边自定义异常处理方法,就是赋给传入JSContext对象con,而不是其外创建的context对象,虽然它们其实是同一个对象。这是因为Block会对内部使用的在外部定义创建的对象做强引用,而JSContext也会对被赋予的Block做强引用,这样它们之间就形成了循环引用(Circular Reference)使得内存无法正常释放。
对于JSValue也不能直接从外部引用到Block中,因为每个JSValue上都有JSContext的引用 (@property(readonly, retain) JSContext *context;),JSContext再引用Block同样也会形成引用循环。


 
0 0
原创粉丝点击