背景
公司项目中有一部分功能牵扯到OC与JS的交互,现有的方式就是通过设置UIWebView
的delegate
方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
去捕获一个请求的url,然后再根据与前端同事提前商量好的一个标记去决定该调用OC的那个方法.
偶然间了解到Android与JS交互的方式很是方便,JS直接可以调用到Android的这边的方法,而且只需要做很少的一部分工作。然后就开始查阅资料,寻找新的方案,就是今天要说的这两个主角JSContext
和JSExport
。
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代码可以获取到关联的类,但是不能获取到相关的方法,更不能调用,截图如下:
另一种方式是直接将一个方法与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
然后再次运行看结果:
这次算是成功了,JS可以直接调用到OC的方法。
结语
这种方式感觉比使用UIWebView
的- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
方法要简便很多,而且代码的可读性也变高了。前段同事也不用针对Android和IOS去做一些区分处理。附上demo地址,如果你觉得对你有帮助不妨点个赞,star下。