OC与JS交互新方案--JSContext与JSExport

背景

公司项目中有一部分功能牵扯到OC与JS的交互,现有的方式就是通过设置UIWebViewdelegate方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType去捕获一个请求的url,然后再根据与前端同事提前商量好的一个标记去决定该调用OC的那个方法.

偶然间了解到Android与JS交互的方式很是方便,JS直接可以调用到Android的这边的方法,而且只需要做很少的一部分工作。然后就开始查阅资料,寻找新的方案,就是今天要说的这两个主角JSContextJSExport

JSContext

官方的文档描述如下:
A JSContext object represents a JavaScript execution environment. You create and use JavaScript contexts to evaluate JavaScript scripts from Objective-C or Swift code, to access values defined in or calculated in JavaScript, and to make native objects, methods, or functions accessible to JavaScript.

于是就开始编码写了一个类用来提供JS调用OC的接口如下:

@interface MNJSCallNataive : NSObject 

- (void)pkgMgrNativeApi:(NSString *)ref;
- (void)pkgMgrNativeApi1:(double)x;

@end

然后将该类通过JSContext与JS关联起来

//MARK:- UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    self.callNative = [[MNJSCallNataive alloc] init];
    _context = JSContext *context = [JSContext currentContext];
    JSValue *value = [JSValue valueWithObject:_callNative inContext:_context];
    [_context setObject:value forKeyedSubscript:@"pkgMgrNativeApi"];
}

奇怪的是当运行起来后JS代码可以获取到关联的类,但是不能获取到相关的方法,更不能调用,截图如下:


类原型为空.png

另一种方式是直接将一个方法与JS关联起来代码如下:

_context[@"func1"] = ^() {
   NSLog(@"js 调用func1");
}

虽然这种方式可行,但是如果方法一多的话就会很麻烦,由此引出我们今天的第二个主角JSExport.

JSExport

官方文档描述如下:
The protocol you implement to export Objective-C classes and their instance methods, class methods, and properties to JavaScript code.
详细的文档大家可以查一下,在这里就不赘述了。
JSExport 是一个协议,如果需要将一个类的实例方法,类方法或属性暴露给JS的话,需要自己自定一个协议,并将需要暴露给JS的方法等在该协议中列出来。具体代码如下:

#import 
#import 

@protocol MNJSCallNataiveProtocol 

- (void)pkgMgrNativeApi:(NSString *)ref;
- (void)pkgMgrNativeApi1:(double)x;

@end

NS_ASSUME_NONNULL_BEGIN

@interface MNJSCallNataive : NSObject 

@end

NS_ASSUME_NONNULL_END

然后再次运行看结果:


原型不为空.png

这次算是成功了,JS可以直接调用到OC的方法。

结语

这种方式感觉比使用UIWebView- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 方法要简便很多,而且代码的可读性也变高了。前段同事也不用针对Android和IOS去做一些区分处理。附上demo地址,如果你觉得对你有帮助不妨点个赞,star下。

你可能感兴趣的:(OC与JS交互新方案--JSContext与JSExport)