iOS OC和JS的交互 javaScriptCore方法封装

时间:2023-03-09 23:48:43
iOS  OC和JS的交互 javaScriptCore方法封装

一、javaScriptCore

javaScriptCore是一种JavaScript引擎,主要为webKit提供脚本处理能力,javaScriptCore是开源webkit的一部分,他提供了强大的整合能力.下面以JS调用OC方法为例,OC调用JS为例说明.

  • JSContext, JSContext是代表JS的执行环境,通过-evaluateScript:方法就可以执行一JS代码
  • JSValue, JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等
  • JSExport, JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用

二、封装源码

注:JSExport 也可实现JS调用OC方法,但是个人感觉过于复杂,不如直接调用直接

还可以使用WebViewJavascriptBridge第三方库去实现,具体的实现方式根据和后台人员商量决定

根据实用性需求,封装出三个方法,一个初始化(要在UIWebview加载完成方法中创建) 一个JS调用OC的方法(id为JS传给OC的参数,id类型为JSValue数组) 一个是OC调用JS的方法(id为OC传递给JS的参数,类型根据需求定义)

// 初始化

+ (instancetype)bridgeForWebView:(UIWebView *)webView;

// JS调OC

- (void)registerHandler:(NSString *)objcName handler:(JSHandler)handler;

// OC调JS

- (void)callHandler:(NSString*)jsName data:(id)data;

/***********************************WebViewJavascriptBridge.h**********************************/

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

#import <JavaScriptCore/JavaScriptCore.h>

@protocol WebViewJavascriptBridgeProtocol <JSExport>

// 通过JS调用OC方法 (采用代理的方法)

- (void)CallOCFunction;

- (void)CallOCFunctionFirstParameter:(NSString *)parameter;

@end

typedef void(^JSResponseCallback)(id responseData);

typedef void(^JSHandler)(id data);

@interface WebViewJavascriptBridge : NSObject <WebViewJavascriptBridgeProtocol>

// 初始化

+ (instancetype)bridgeForWebView:(UIWebView *)webView;

// JS调OC

- (void)registerHandler:(NSString *)objcName handler:(JSHandler)handler;

// OC调JS

- (void)callHandler:(NSString*)jsName data:(id)data;

@end

/***********************************WebViewJavascriptBridge.m**********************************/

#import "WebViewJavascriptBridge.h"

@interface WebViewJavascriptBridge ()

{

JSContext *_jsContext;

UIWebView *_webView;

}

@end

@implementation WebViewJavascriptBridge

static WebViewJavascriptBridge * gThis = nil;

+ (WebViewJavascriptBridge *) instance

{

if ( gThis == nil ){

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

gThis = [[WebViewJavascriptBridge alloc] init];

});

}

return gThis;

}

+ (instancetype)bridgeForWebView:(UIWebView *)webView {

WebViewJavascriptBridge *bridge = [self instance];

[bridge platformSpecificSetup:webView];

return bridge;

}

- (void)platformSpecificSetup:(UIWebView *)webView {

_webView = webView;

// 对JSContext对象进行初始化

_jsContext = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

// 验证JSContext对象是否初始化成功

_jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {

context.exception = exception;

NSLog(@"异常信息:%@", exception);

};

}

#pragma mark - public

// objcName : oc函数名

// handler  : block回调

- (void)registerHandler:(NSString *)objcName handler:(JSHandler)handler {

// 创建objcEcho对象赋值给js对象self

//    _jsContext[objcName] = self;

// JS调用OC函数

_jsContext[objcName] = ^() {

// 获取JS传来的参数 (JSValue对象数组)

NSArray *args = [JSContext currentArguments];

// 回调

handler(args);

};

}

// jsName : js函数名

// data   : 传给js的参数

// responseCallback 回调

- (void)callHandler:(NSString*)jsName data:(id)data {

// OC调用JS函数

JSValue *jsValue = _jsContext[jsName];

// 传字典

//    NSDictionary *dict = @{@"key1" : @"参数1", @"key2" : @"参数2"};

// 传对象

//    Person *person = [[Person alloc] init];

//    JSValue *value = [JSValue valueWithObject:person inContext:_jsContext];

//    [value setValue:@"朱凯巍" forProperty:@"name"];

//    [value setValue:@(10) forProperty:@"age"];

// OC为JS传参数

[jsValue callWithArguments:@[data]];

}

#pragma mark - JSWebViewObjectProtocol

// 通过JS调用OC方法

- (void)CallOCFunction {

NSLog(@"%s",__func__);

}

- (void)CallOCFunctionFirstParameter:(NSString *)parameter {

NSLog(@"%s",__func__);

}