IOS中 使用JavaScriptCore 實現OC與JS的交互

轉: http://www.jianshu.com/p/cdaf9bc3d65d


一、說明

這篇文章記錄自己在研究OC與JS交互中的所得,以及遇到的問題與解決

由於蘋果的審覈時間太漫長,一次審覈不過,那又將進入另一個漫長的審覈期。爲了能在開發中方便更新,公司要求在項目中使用HTML5,這樣就涉及到OC與JS的交互,不懂H5,不懂JS。在經過一段時間的摸索之後,將自己的研究記錄下來,以做備忘。

OC與JS的交互實現方式有很多,之前用的比較多的是WebViewJavaScriptBridge,但在IOS7之後,蘋果將JavaScriptCore框架開放。因此,這篇文章不講理論,主要講的是JavaScriptCore的實際使用。

文中所用的項目JavaScriptCoreDemo

廢話說完了,下面進入正題

二、Demo項目中功能介紹


Demo首頁

這個demo主要分爲了三個部分來:
1.JS Call OC , JS調用OC的函數
2.OC Call JS , OC調用JS的函數
3.一個繪圖的例子

在做OC與JS交互工作之前,我們需要做些準備工作

1.導入JavaScriptCore的頭文件

#import <JavaScriptCore/JavaScriptCore.h>

2.用webView加載HTML文件,這裏用的是本地HTML;

- (void)viewDidLoad
{
[super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
self.title = @"js call oc";

NSString *path = [[[NSBundle mainBundle] bundlePath]  stringByAppendingPathComponent:@"JSCallOC.html"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]];
[self.webView loadRequest:request];
}

3.在JS交互中,很多事情都是在webView的delegate方法中完成的,通過JSContent創建一個使用JS的環境,所以這裏,我們先將self.content在這裏面初始化;

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
 //初始化content
 self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

// 打印異常,由於JS的異常信息是不會在OC中被直接打印的,所以我們在這裏添加打印異常信息,
self.context.exceptionHandler =
^(JSContext *context, JSValue *exceptionValue)
{
    context.exception = exceptionValue;
    NSLog(@"%@", exceptionValue);
};
}

三、實際操作中 JS call OC

先來看demo


JS Call OC

這個頁面整個都是通過HTML實現的,
1 計算階乘:在輸入框中輸入一個數字,然後在OC中計算出結果,最後顯示在HTML的頁面上;
2 測試log:點擊後,在後臺打印測試數據;
3 OC原生Alert :點擊後,彈出OC的提示框;
4 addSubView:點擊後,在OC中添加一個View;
5 push to second ViewController :跳轉到下一個界面

總結:以上功能都是在OC獲取HTML中按鈕的點擊事件,在後在OC中實現功能

??如何獲取HTML中的點擊事件呢??

在HTML中,爲一個元素添加點擊時間有兩種寫法

    <input type="button" value="計算階乘" οnclick="native.calculateForJS(input.value);" />

或者

<input type="button" value="測試log" οnclick="log('測試');" />
如果是第一種方法,

那麼就要用JSExport協議關聯native的方法,要在webView的delegate裏面添加

 // 以 JSExport 協議關聯 native 的方法
self.content[@"native"] = self;

添加完之後,要聲明一個繼承JSExport的協議,協議中聲明供JS使用的OC的方法

@protocol TestJSExport <JSExport>
JSExportAs
(calculateForJS  /** handleFactorialCalculateWithNumber 作爲js方法的別名 */,
 - (void)handleFactorialCalculateWithNumber:(NSNumber *)number
 );
- (void)pushViewController:(NSString *)view title:(NSString *)title;

-(void)log:(NSString*)l;

@end

在OC中實現這些方法,這樣就完成了!

如果是第二章方法,則只需要通過block的形式關聯JavaScript function就可以了!
self.context[@"log"] = ^(NSString *str)
{
NSLog(@"%@", str);
};

三、OC調用JS


OC調用JS


在這個例子中,界面的所有View都是OC創建的,點擊“交給JS處理計算階乘”後,將textfild的數據傳給JS,JS計算完成後在返回來!

這裏面首先要獲取JS裏面的計算函數,在OC中,所有表示JS中對象,都用JSValue來創建,通過objectForKeyedSubscript方法或者直接使用下標的方法獲取JS對象,然後使用callWithArguments方法來執行函數

// 方法一.   JSValue *function = [self.context objectForKeyedSubscript:@"factorial"];
// 方法二.
JSValue * function = self.context[@"factorial"];
JSValue *result = [function callWithArguments:@[inputNumber]];
self.showLable.text = [NSString stringWithFormat:@"%@", [result toNumber]];

四、demo之外(慢慢在總結)

1.JS注入
2.在OC中爲JS創建對象
......

零碎的補充1:對於JS 函數中,參數中有函數的,在OC中用JSValue接收

 // 比如:JS代碼
 function  myFunc({"text":"這裏是文字","callbackFun":function(string){alert'string'}});

//OC代碼中在.h的protocol中聲明JS要調用的OC方法
//.h protocol中,函數名稱要和JS中相同,這裏接收的參數爲JSValue
JSExportAs
(myFunc,
 -(void) myFunc:(JSValue*)value
 );

//在.m文件中,實現myFunc方法
-(void) myFunc:(JSValue*)value{

NSString * text = [value valueForProperty:@"text"];//打印"這裏是文字"

JSValue * func =  [value valueForProperty:@"callbackFun"]; //這裏是JS參數中的func;

//調用這個函數
[func callWithArguments:@[@"這裏是參數"]];

}


文/brian0419(簡書作者)
原文鏈接:http://www.jianshu.com/p/cdaf9bc3d65d
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章