OC 與 JS 交互之 JavaScriptCore

JavaScriptCore 是 JavaScript 的虛擬機(jī)今阳,是一個(gè)WebKit的運(yùn)行環(huán)境绿语,為 JavaScript 的執(zhí)行提供底層資源写隶。我們可以利用 JavaScriptCore 中的類及協(xié)議赡盘,進(jìn)行 OC 與 JS 的交互。

JavaScriptCore中類及協(xié)議:
JSContext

給JavaScript提供運(yùn)行的上下文環(huán)境懂更,像是前端開發(fā)中的面對(duì)瀏覽器的 window 對(duì)象,代表運(yùn)行時(shí)的一個(gè)全局變量阿趁;
通過(guò) -evaluateScript: 方法就可以執(zhí)行一JS代碼膜蛔,其返回值是JavaScript代碼中最后一個(gè)生成的值;
JSContext的exceptionHandler屬性可用來(lái)接收J(rèn)avaScript中拋出的異常

JSValue

封裝了JS與OC中的對(duì)應(yīng)的類型脖阵,一個(gè)用來(lái)處理iOS中所有可能存在的JavaScript執(zhí)行后產(chǎn)生Value的類皂股,可以用來(lái)轉(zhuǎn)換基本數(shù)據(jù)類型

JSManagedValue

管理數(shù)據(jù)和方法的類,包含一個(gè)JSValue對(duì)象命黔,有條件地持有對(duì)象

JSVirtualMachine

完整獨(dú)立的JavaScript執(zhí)行環(huán)境呜呐,為JavaScript的執(zhí)行提供底層資源,實(shí)現(xiàn)并發(fā)的JavaScript執(zhí)行悍募,JavaScript和OC橋接對(duì)象的內(nèi)存管理

JSExport

這是一個(gè)協(xié)議蘑辑,如果采用協(xié)議的方法交互,自己定義的協(xié)議必須遵守此協(xié)議坠宴,在協(xié)議中聲明的API都會(huì)在JS中暴露出來(lái)洋魂,才能調(diào)用

OC調(diào)用JS
JSContext *context = [[JSContext alloc] init];
[context evaluateScript:@"function add(a,b) {return a + b;}"];
    
//1.取出方法名,調(diào)用
JSValue *add = context[@"add"];
JSValue *sum = [add callWithArguments:@[@7,@8]];
NSLog(@"Sum1: %d", [sum toInt32]);
    
//2.將調(diào)用過(guò)程繼續(xù)寫進(jìn)JSContext里,調(diào)用
JSValue *addValue = [context evaluateScript:@"add(7, 8)"];
NSLog(@"Sum2: %@", addValue.toNumber);
JS調(diào)用OC

1.block方式

JSContext *context = [[JSContext alloc] init];
context[@"log"] = ^(){
    NSLog(@"----------Begin log----------");
    NSArray *args = [JSContext currentArguments];
    for (JSValue *jsVal in args) {
        NSLog(@"%@", jsVal);
    }
        
    JSValue *this = [JSContext currentThis];
    NSLog(@"This: %@", this);
    NSLog(@"-----------End log-----------");
};

//web 頁(yè)面可調(diào)用 log 方法副砍,傳入相關(guān)參數(shù)衔肢,調(diào)用OC端的block,這里直接用 JSContext 執(zhí)行 JS 代碼
[context evaluateScript:@"log('apple',['array1', 'array2'],{key1:'value1',key2:'value2',key3:'value3'});"];
用 block 方式使 JS 調(diào)用 OC 代碼

從圖中可以看出豁翎,JSValue 對(duì)于 JS 類型到 OC 類型的處理并不一致角骤,具體如下:

JSValue 作為 OC 類型與 JS 類型的橋梁

2.使用 webview
首先,在工程中新建一個(gè) Empty 文件心剥,命名為 test.html 邦尊,代碼如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
            <title>test javascript</title>
    </head>
    <body>
        <div>
            <button onclick="zn.a('JS與OC交互');">請(qǐng)看xcode的log</button>
        </div>
    </body>
</html>

然后,新建一個(gè) model 類优烧,此類必須遵守一個(gè)‘遵守 JSExport 協(xié)議’的協(xié)議蝉揍,如果想要將一個(gè)自定義類的方法暴露給外部的JavaScript使用,那么這個(gè)類必須遵守JSExport協(xié)議匙隔,JSExport協(xié)議提供了一種聲明式的方法去向JavaScript代碼導(dǎo)出Objective-C的實(shí)例類及其實(shí)例方法疑苫,類方法和屬性:

@protocol PersonJSExport <JSExport>
//將 JS 中的調(diào)用方法名與model類中的相對(duì)應(yīng)
JSExportAs(a, - (void)nslog:(NSString *)string);
@end

在model類中實(shí)現(xiàn)協(xié)議:

- (void)nslog:(NSString *)string
{
    NSLog(@"%@", string);
}

最后,在 controller 中新添一個(gè) webview 纷责,這個(gè) webview 加載剛剛新建的 test.html 中的內(nèi)容:

- (UIWebView *)webView
{
    if (_webView == nil) {
        _webView = [[UIWebView alloc] initWithFrame:self.view.frame];
        
        NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
        NSString *htmlContent = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"] encoding:NSUTF8StringEncoding error:nil];
        
        [_webView loadHTMLString:htmlContent baseURL:baseURL];
       
        JSContext *context = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        JsObjCModel *jsOCModel = [JsObjCModel new];
        //給js中的對(duì)象賦值
        context[@"zn"] = jsOCModel;
    }
    return _webView;
}

JSContext 是通過(guò) webView 的 valueForKeyPath 獲取的捍掺,其路徑為documentView.webView.mainFrame.javaScriptContext;
將一個(gè)初始化好的再膳、可以執(zhí)行協(xié)議中方法的model類賦值給 JS 中定義的一個(gè)對(duì)象挺勿,在點(diǎn)擊 html 頁(yè)面上的 button 后,JS 執(zhí)行 OC 方法喂柒。

屏幕快照 2017-08-17 下午9.17.31.png

參考博客:
JavaScriptCore全面解析
JavaScriptCore
WebView 與 JS 的幾種交互

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末不瓶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子灾杰,更是在濱河造成了極大的恐慌蚊丐,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艳吠,死亡現(xiàn)場(chǎng)離奇詭異麦备,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)昭娩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門凛篙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人栏渺,你說(shuō)我怎么就攤上這事呛梆。” “怎么了磕诊?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵填物,是天一觀的道長(zhǎng)纹腌。 經(jīng)常有香客問我,道長(zhǎng)滞磺,這世上最難降的妖魔是什么壶笼? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮雁刷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘保礼。我一直安慰自己沛励,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布炮障。 她就那樣靜靜地躺著目派,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胁赢。 梳的紋絲不亂的頭發(fā)上企蹭,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音智末,去河邊找鬼谅摄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛系馆,可吹牛的內(nèi)容都是我干的送漠。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼由蘑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼闽寡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起尼酿,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤爷狈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后裳擎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涎永,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年句惯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了土辩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抢野,死狀恐怖拷淘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情指孤,我是刑警寧澤启涯,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布贬堵,位于F島的核電站,受9級(jí)特大地震影響结洼,放射性物質(zhì)發(fā)生泄漏黎做。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一松忍、第九天 我趴在偏房一處隱蔽的房頂上張望蒸殿。 院中可真熱鬧,春花似錦鸣峭、人聲如沸宏所。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)爬骤。三九已至,卻和暖如春莫换,著一層夾襖步出監(jiān)牢的瞬間霞玄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工拉岁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坷剧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓喊暖,卻偏偏與公主長(zhǎng)得像听隐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哄啄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容