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__);

}