日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

js与c语言互相调用,Objc与JS间相互调用

發(fā)布時間:2025/3/15 javascript 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js与c语言互相调用,Objc与JS间相互调用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

過去3、4年都在進(jìn)行跨平臺的混合應(yīng)用開發(fā),但一直沒有系統(tǒng)梳理跨平臺技術(shù)的底層原理,趁新工作未正式入職,這里整理一下。

跨平臺的一種實現(xiàn)是基于webview。所謂webview,實質(zhì)是在原生app中打開一個內(nèi)嵌瀏覽器,具體到iOS平臺就是使用UIWebView這個控件。然后就很容易理解了,我們相當(dāng)于開發(fā)一個webapp(網(wǎng)頁應(yīng)用),然后通過原生應(yīng)用作為用戶入口(而非原生瀏覽器),用戶會訪問到遠(yuǎn)程服務(wù)器的網(wǎng)頁內(nèi)容。從用戶感知上,似乎是在使用一個App,但實際上是在訪問一個網(wǎng)頁。

以上,只是跨平臺基于webview實現(xiàn)的工作原理,而更重要的是如何橋接webview的js和app的objc,使得webapp也可用使用原生的功能api,如調(diào)用攝像頭等,而app又可以調(diào)用webview里的js,即向雙通信。

Apple開放了一個叫做JavascriptCore的框架,此框架最早在OSX10.2就存在,但到了2013年在OSX10.9上才發(fā)布其調(diào)用的API,而后又在iOS7上公開,由此我們可用名正言順地使用了。

JavascriptCore提供了以下幾個API,實現(xiàn)跨平臺通信:

JavascriptCore/API/JSContext.h

JavascriptCore/API/JSExport.h

JavascriptCore/API/JSValue.h

JSContext是JavascriptCore的主入口,它代表了JS的運(yùn)行時環(huán)境,在其中可以定義對象、方法等,這些實體(對象、方法)的生命周期在JSContext被釋放的時候才結(jié)束。而且可用指定的JSVirtualMachine來創(chuàng)建JSContext,每個JSVM都會獨(dú)立運(yùn)行在一個線程上。

我們可用通過JSContext的evaluateScript方法來定義我們的JS方法,而且是通過字符串定義代碼,當(dāng)然可以通過讀取外邊js文件來實現(xiàn)。看下面的例子:

// getting a JSContext

JSContext *context = [JSContext new];

// defining a JavaScript function

NSString *jsFunctionText =

@"var isValidNumber = function(phone) {"

" var phonePattern = /^[0-9]{3}[ ][0-9]{3}[-][0-9]{4}$/;"

" return phone.match(phonePattern) ? true : false;"

"}";

[context evaluateScript:jsFunctionText];

這里,相當(dāng)于在objc層,向JSContext注入了一個isValidNumber的js方法。

正如上文所述,JSContext代表了一個JS運(yùn)行環(huán)境,而我們的示例代碼都是單獨(dú)創(chuàng)建這個JSContext運(yùn)行環(huán)境的,實際上UIWebView實例也有它自己的JSContext運(yùn)行環(huán)境。為了修改web上的內(nèi)容,我們需要訪問UIWebView的JSContext。

但Apple就是一個悶騷男,雖然已經(jīng)公開了JavascriptCore的API,但又不提供直接訪問UIWebView’s JSContext的方法。

幸好“key-value”把我們救了回來:

// get JSContext from UIWebView instance

JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

然后,我們可以通過JSValue來獲取JSContext中js方法的引用和執(zhí)行的結(jié)果:

// 獲取isValidNumber方法的引用

JSValue *jsFunction = context[@"isValidNumber"];

// 通過callWithArguments方法調(diào)用js方法

JSValue *value = [jsFunction callWithArguments:@[ phone ]];

JavascriptCore會自動轉(zhuǎn)換JSValue的對象類型,比如這里isValidNumber返回的boolean,同時還支持NSString, NSDate, NSDictionary, NSArray等。

另外,我們還可以增加異常捕捉

[context setExceptionHandler:^(JSContext *context, JSValue *value) {

NSLog(@"%@", value);

}];

再有,通過JSExport可以將objc的方法暴露給JS。

@protocol BNRContactAppJS

- (void)addContact:(BNRContact *)contact;

@end

@interface BNRContactApp : NSObject

...

@end

addContact這個方法是在BNRContactAppJS協(xié)議中聲明的,BNRContactAppJS又源自于JSExport,所以addContact方法將會暴露給JS環(huán)境,而其他方法則對JS環(huán)境而言是隱藏的。

最后,我們看一個完整的例子

- (void)webViewDidFinishLoad:(UIWebView *)webView

{

// get JSContext from UIWebView instance

JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

// enable error logging

[context setExceptionHandler:^(JSContext *context, JSValue *value) {

NSLog(@"WEB JS: %@", value);

}];

// give JS a handle to our BNRContactApp instance

context[@"myApp"] = self.app;

// register BNRContact class

context[@"BNRContact"] = [BNRContact class];

// add function for processing form submission

NSString *addContactText =

@"var contactForm = document.forms[0];"

"var addContact = function() {"

" var name = contactForm.name.value;"

" var phone = contactForm.phone.value;"

" var address = contactForm.address.value;"

" var contact = BNRContact.contactWithNamePhoneAddress(name, phone, address);"

" myApp.addContact(contact);"

"};"

"contactForm.addEventListener('submit', addContact);";

[context evaluateScript:addContactText];

}

最終跨平臺調(diào)用就在這一句:

myApp.addContact(contact);

在JS環(huán)境調(diào)用了objc的方法。

總結(jié)一下:

==從objc調(diào)用js:JSContext的evaluateScriptf方法和JSValue的callWithArguments方法;==

==捕捉JS執(zhí)行的異常;==

==從WebView實例獲取JSContext;==

==通過JSExport將objc方法暴露給js調(diào)用。==

最后啰嗦一下,iOS7以前,并沒有JavascriptCore,所以多使用 stringByEvaluatingJavaScriptFromString。

Titanium 就是使用了JavascriptCore的方式。

總結(jié)

以上是生活随笔為你收集整理的js与c语言互相调用,Objc与JS间相互调用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。