iOS與Javascript交互實戰

本教程中所涉及到的幾種類型:

JSContext, JSContext是代表JS的執行環境,通過-evaluateScript:方法就可以執行一JS代碼

JSValue, JSValue封裝了JS與ObjC中的對應的類型,以及調用JS的API等

JSExport, JSExport是一個協議,遵守此協議,就可以定義我們自己的協議,在協議中聲明的API都會在JS中暴露出來,才能調用

ObjC與JS交互方式

通過JSContext,我們有兩種調用JS代碼的方法:

1、直接調用JS代碼

2、在ObjC中通過JSContext注入模型,然后調用模型的方法

直接調用JS代碼

// 一個JSContext對象,就類似于Js中的window,

// 只需要創建一次即可。

self.jsContext = [[JSContext alloc] init];

//? jscontext可以直接執行JS代碼。

[self.jsContext evaluateScript:@"var num = 10"];

[self.jsContext evaluateScript:@"var squareFunc = function(value) { return value * 2 }"];

// 計算正方形的面積

JSValue *square = [self.jsContext evaluateScript:@"squareFunc(num)"];

// 也可以通過下標的方式獲取到方法

JSValue *squareFunc = self.jsContext[@"squareFunc"];

JSValue *value = [squareFunc callWithArguments:@[@"20"]];

NSLog(@"%@", square.toNumber);

NSLog(@"%@", value.toNumber);

這種方式是沒有注入模型到JS中的。這種方式使用起來不太合適,通常在JS中有很多全局的函數,為了防止名字重名,使用模型的方式是最好不過了。通過我們協商好的模型名稱,在JS中直接通過模型來調用我們在ObjC中所定義的模型所公開的API。

通過注入模型的方式交互

首先,我們需要先定義一個協議,而且這個協議必須要遵守JSExport協議。

@protocol JavaScriptObjectiveCDelegate// JS調用此方法來調用OC的系統相冊方法

- (void)callSystemCamera;

// 在JS中調用時,函數名應該為showAlertMsg(arg1, arg2)

// 這里是只兩個參數的。

- (void)showAlert:(NSString *)title msg:(NSString *)msg;

// 通過JSON傳過來

- (void)callWithDict:(NSDictionary *)params;

// JS調用Oc,然后在OC中通過調用JS方法來傳值給JS。

- (void)jsCallObjcAndObjcCallJsWithDict:(NSDictionary *)params;

@end

接下來,我們還需要定義一個模型:// 此模型用于注入JS的模型,這樣就可以通過模型來調用方法。@interface HYBJsObjCModel : NSObject@property (nonatomic, weak) JSContext *jsContext;

@property (nonatomic, weak) UIWebView *webView;

@end

實現這個模型:

@implementation HYBJsObjCModel

- (void)callWithDict:(NSDictionary *)params {

NSLog(@"Js調用了OC的方法,參數為:%@", params);

}

// Js調用了callSystemCamera

- (void)callSystemCamera {

NSLog(@"JS調用了OC的方法,調起系統相冊");

// JS調用后OC后,又通過OC調用JS,但是這個是沒有傳參數的

JSValue *jsFunc = self.jsContext[@"jsFunc"];

[jsFunc callWithArguments:nil];

}

- (void)jsCallObjcAndObjcCallJsWithDict:(NSDictionary *)params {

NSLog(@"jsCallObjcAndObjcCallJsWithDict was called, params is %@", params);

// 調用JS的方法

JSValue *jsParamFunc = self.jsContext[@"jsParamFunc"];

[jsParamFunc callWithArguments:@[@{@"age": @10, @"name": @"lili", @"height": @158}]];

}

- (void)showAlert:(NSString *)title msg:(NSString *)msg {

dispatch_async(dispatch_get_main_queue(), ^{

UIAlertView *a = [[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];

[a show];

});

}

@end

接下來,我們在controller中在webview加載完成的代理中,給JS注入模型。

#pragma mark - UIWebViewDelegate

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

self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

// 通過模型調用方法,這種方式更好些。

HYBJsObjCModel *model? = [[HYBJsObjCModel alloc] init];

self.jsContext[@"OCModel"] = model;

model.jsContext = self.jsContext;

model.webView = self.webView;

self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {

context.exception = exceptionValue;

NSLog(@"異常信息:%@", exceptionValue);

};

}

我們是通過webView的valueForKeyPath獲取的,其路徑為documentView.webView.mainFrame.javaScriptContext。

這樣就可以獲取到JS的context,然后為這個context注入我們的模型對象。

我們先寫兩個JS方法:

var jsFunc = function() {

alert('Objective-C call js to show alert');

}

var jsParamFunc = function(argument) {

document.getElementById('jsParamFuncSpan').innerHTML

= argument['name'];

}

這里我們定義了兩個JS方法,一個是jsFunc,不帶參數。

另一個是jsParamFunc,帶一個參數。

接下來,我們在html中的body中添加以下代碼:

Test how to use objective-c call js

現在就可以測試代碼了。當我們點擊第一個按鈕:Call ObjC system camera時,通過OCModel.callSystemCamera(),就可以在HTML中通過JS調用OC的方法。在OC代碼中,我們的callSystemCamera方法體中,添加了以下兩行代碼,就是獲取HTML中所定義的JS就去jsFunc,然后調用它。 JSValue *jsFunc = self.jsContext[@"jsFunc"]; [jsFunc callWithArguments:nil];這樣就可以在JS調用OC方法時,也讓OC反饋給JS。看看下面傳字典參數:

- (void)jsCallObjcAndObjcCallJsWithDict:(NSDictionary *)params { NSLog(@"jsCallObjcAndObjcCallJsWithDict was called, params is %@", params); // 調用JS的方法 JSValue *jsParamFunc = self.jsContext[@"jsParamFunc"]; [jsParamFunc callWithArguments:@[@{@"age": @10, @"name": @"lili", @"height": @158}]];}獲取我們在HTML中定義的jsParamFunc方法,然后調用它并傳了一個字典作為參數。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容

  • 因為項目需要做一個活動,而這個活動的信息是源于HTML5寫的,而這個操作網頁的過程上, 是需要到與原生APP這邊交...
    貝勒老爺閱讀 466評論 3 5
  • 前言 ObjectiveC與Js交互是常見的需求,可對于新手或者所謂的高手而言,其實并不是那么簡單明了。這里只介紹...
    一路向北客閱讀 367評論 0 4
  • 隨著H5技術的興起,在iOS開發過程中,難免會遇到原生應用需要和H5頁面交互的問題。其中會涉及方法調用及參數傳值等...
    Chris_js閱讀 3,104評論 1 8
  • 跟原生開發相比,H5的開發相對來一個成熟的框架和團隊來講在開發速度和開發效率上有著比原生很大的優勢,至少不用等待審...
    大沖哥閱讀 1,858評論 0 7
  • 曾經服務的一家公司,在每年年終績效考核的時候,有一項關于Self awareness的評分。當時覺得這一項設置很可...
    莊艷Ellen閱讀 473評論 0 50