轉: http://www.jianshu.com/p/cdaf9bc3d65d
一、說明
這篇文章記錄自己在研究OC與JS交互中的所得,以及遇到的問題與解決
由於蘋果的審覈時間太漫長,一次審覈不過,那又將進入另一個漫長的審覈期。爲了能在開發中方便更新,公司要求在項目中使用HTML5,這樣就涉及到OC與JS的交互,不懂H5,不懂JS。在經過一段時間的摸索之後,將自己的研究記錄下來,以做備忘。
OC與JS的交互實現方式有很多,之前用的比較多的是WebViewJavaScriptBridge,但在IOS7之後,蘋果將JavaScriptCore框架開放。因此,這篇文章不講理論,主要講的是JavaScriptCore的實際使用。
文中所用的項目JavaScriptCoreDemo
廢話說完了,下面進入正題
二、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
這個頁面整個都是通過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
在這個例子中,界面的所有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:@[@"這裏是參數"]];
}
原文鏈接:http://www.jianshu.com/p/cdaf9bc3d65d
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。