原文轉(zhuǎn)自:http://zonble.net/archives/2010_09/1385.php在寫 JavaScript 的時候抖仅,可以使用一個叫做 window 的對象剔桨,像是我們想要從現(xiàn)在的網(wǎng)頁跳到另外一個網(wǎng)頁的時候,就會去修改 window.location.href 的位置乖菱;在我們的 Objective C 程序碼中,如果我們可以取得指定的 WebView 的指標(biāo),也就可以拿到這個出現(xiàn)在 JavaScript 中的 window 對象退子,也就是 [webView windowScriptObject]。
這個對象就是 WebView 里頭的 JS 與我們的 Obj C 程序之間的橋樑-window 對象可以取得網(wǎng)頁里頭所有的 JS 函數(shù)與對象型将,而如果我們把一個 Obj C 對象設(shè)定成 windowScriptObject 的 value寂祥,JS 也便可以調(diào)用 Obj C 對象的 method。于是七兜,我們可以在 Obj C 程序里頭要求 WebView 執(zhí)行一段 JS丸凭,也可以反過來讓 JS 調(diào)用一段用 Obj C 實(shí)作的功能。
※ 用 Objective C 取得與設(shè)定 JavaScript 對象
要從 Obj C 取得網(wǎng)頁中的 JavaScript 對象腕铸,也就是對 windowScriptObject 做一些 KVC 調(diào)用惜犀,像是 valueForKey: 與 valueForKeyPath:。如果我們在 JS 里頭狠裹,想要知道目前的網(wǎng)頁位置虽界,會這麼寫:
1
varlocation = window.location.href;
varlocation = window.location.href;
用 ObjC 就可以這麼調(diào)用:
1
NSString*location = [[webView windowScriptObject] valueForKeyPath:@"location.href"];
NSString*location = [[webView windowScriptObject] valueForKeyPath:@"location.href"];
如果我們要設(shè)定 window.location.href,要求開啟另外一個網(wǎng)頁涛菠,在 JS 里頭:
1
window.location.href ='http://spring-studio.net';
window.location.href ='http://spring-studio.net';
Obj C:
1
[[webView windowScriptObject] setValue:@"http://spring-studio.net"forKeyPath:@"location.href"];
[[webView windowScriptObject] setValue:@"http://spring-studio.net"forKeyPath:@"location.href"];
由于 Obj C 與 JS 本身的語言特性不同莉御,在兩種語言之間相互傳遞東西之間撇吞,就可以看到兩者的差別-
JS 雖然是 OO,但是并沒有 class礁叔,所以將 JS 對象傳到 Obj C 程序里頭牍颈,除了基本字串會轉(zhuǎn)換成 NSString、基本數(shù)字會轉(zhuǎn)成 NSNumber晴圾,像是 Array 等其他對象犀填,在 Obj C 中趁桃,都是 WebScriptObject 這個 Class玷过。意思就是笋颤,JS 的 Array 不會幫你轉(zhuǎn)換成 NSArray。
從 JS 里頭傳一個空對象給 Obj C 程序都毒,用的不是 Obj C 里頭原本表示「沒有東西」的方式色罚,像是 NULL、nil账劲、NSNull 等戳护,而是專屬 WebKit 使用的 WebUndefined。
所以瀑焦,如果我們想要看一個 JS Array 里頭有什麼東西腌且,就要先取得這個對象里頭叫做 length 的 value,然后用 webScriptValueAtIndex: 去看在該 index 位置的內(nèi)容榛瓮。假如我們在 JS 里頭這樣寫:
1
2
3
4
varJSArray = {'zonble','dot','net'};
for(vari = 0; i < JSArray.length; i++) {
console.log(JSArray[i]);
}
varJSArray = {'zonble','dot','net'};for(vari = 0; i < JSArray.length; i++) { console.log(JSArray[i]);}
Obj C 里頭就會變成這樣:
1
2
3
4
5
6
7
8
WebScriptObject obj = (WebScriptObject )JSArray;
NSUIntegercount = [[obj valueForKey:@"length"] integerValue];
NSMutableArraya = [NSMutableArrayarray];
for(NSUIntegeri = 0; i < count; i++) {
NSStringitem = [obj webScriptValueAtIndex:i];
NSLog(@"item:%@", item);
}
WebScriptObject obj = (WebScriptObject )JSArray;NSUIntegercount = [[obj valueForKey:@"length"] integerValue];NSMutableArraya = [NSMutableArrayarray];for(NSUIntegeri = 0; i < count; i++) { NSStringitem = [obj webScriptValueAtIndex:i]; NSLog(@"item:%@", item);}
※ 用 Objective C 調(diào)用 JavaScript function
要用 Obj C 調(diào)用網(wǎng)頁中的 JS function铺董,大概有幾種方法。第一種是直接寫一段跟你在網(wǎng)頁中會撰寫的 JS 一模一樣的程序禀晓,叫 windowScriptObject 用 evaluateWebScript: 執(zhí)行精续。例如,我們想要在網(wǎng)頁中產(chǎn)生一個新的 JS function粹懒,內(nèi)容是:
1
2
3
functionx(x) {
returnx + 1;
}
functionx(x) { returnx + 1;}
所以在 Obj C 中可以這樣寫重付;
1
[[webView windowScriptObject] evaluateWebScript:@"function x(x) { return x + 1;}"];
[[webView windowScriptObject] evaluateWebScript:@"function x(x) { return x + 1;}"];
接下來我們就可以調(diào)用 window.x():
1
2
NSNumber*result = [[webView windowScriptObject] evaluateWebScript:@"x(1)"];
NSLog(@"result:%d", [result integerValue]);// Returns 2
NSNumber*result = [[webView windowScriptObject] evaluateWebScript:@"x(1)"];NSLog(@"result:%d", [result integerValue]);// Returns 2
由于在 JS 中,每個 funciton 其實(shí)都是對象凫乖,所以我們還可以直接取得 window.x 叫這個對象執(zhí)行自己确垫。在 JS 里頭如果這樣寫:
1
window.x.call(window.x, 1);
window.x.call(window.x, 1);
Obj C 中便是這樣:
1
2
WebScriptObject x = [[webView windowScriptObject] valueForKey:@"x"];
NSNumberresult = [x callWebScriptMethod:@"call"withArguments:[NSArrayarrayWithObjects:x, [NSNumbernumberWithInt:1],nil]];
WebScriptObject x = [[webView windowScriptObject] valueForKey:@"x"];NSNumberresult = [x callWebScriptMethod:@"call"withArguments:[NSArrayarrayWithObjects:x, [NSNumbernumberWithInt:1],nil]];
這種讓某個 WebScriptObject 自己執(zhí)行自己的寫法,其實(shí)比較不會用于從 Obj C 調(diào)用 JS 這一端帽芽,而是接下來會提到的删掀,由 JS 調(diào)用 Obj C,因?yàn)檫@樣 JS 就可以把一個 callback function 送到 Obj C 程序里頭嚣镜。
如果我們在做網(wǎng)頁爬迟,我們只想要更新網(wǎng)頁中的一個區(qū)塊橘蜜,就會利用 AJAX 的技巧菊匿,只對這個區(qū)塊需要的資料付呕,對 server 發(fā)出 request,并且在 request 完成的時候跌捆,要求執(zhí)行一段 callback function徽职,更新這一個區(qū)塊的顯示內(nèi)容。從 JS 調(diào)用 Obj C也可以做類似的事情佩厚,如果 Obj C 程序里頭需要一定時間的運(yùn)算姆钉,或是我們可能是在 Obj C 里頭抓取網(wǎng)路資料,我們便可以把一個 callback function 送到 Obj C 程序裡抄瓦,要求 Obj C 程序在做完工作后潮瓶,執(zhí)行這段 callback function。
※ DOM
WebKit 里頭钙姊,所有的 DOM 對象都繼承自 DOMObject毯辅,DOMObject 又繼承自 WebScriptObject,所以我們在取得了某個 DOM 對象之后煞额,也可以從 Obj C 程序中思恐,要求這個 DOM 對象執(zhí)行 JS 程序。
假如我們的網(wǎng)頁中膊毁,有一個 id 叫做 “#s” 的文字輸入框(text input)胀莹,而我們希望現(xiàn)在鍵盤輸入的焦點(diǎn)放在這個輸入框上,在 JS 里頭會這樣寫:
1
document.querySelector('#s').focus();
document.querySelector('#s').focus();
Obj C:
1
2
DOMDocument *document = [[webView mainFrame] DOMDocument];
[[document querySelector:@"#s"] callWebScriptMethod:@"focus"withArguments:nil];
DOMDocument *document = [[webView mainFrame] DOMDocument];[[document querySelector:@"#s"] callWebScriptMethod:@"focus"withArguments:nil];
※ 用 JavaScript 存取 Objective C 的 Value
要讓網(wǎng)頁中的 JS 程序可以調(diào)用 Obj C 對象婚温,方法是把某個 Obj C 對象注冊成 JS 中 window 對象的屬性描焰。之后,JS 便也可以調(diào)用這個對象的 method缭召,也可以取得這個對象的各種 Value栈顷,只要是 KVC 可以取得的 Value,像是 NSString嵌巷、NSNumber萄凤、NSDate、NSArray搪哪、NSDictionary靡努、NSValue…等。JS 傳 Array 到 ObjC 時晓折,還需要特別做些處理才能變成 NSArray惑朦,從 Obj C 傳一個 NSArray 到 JS 時,會自動變成 JS Array漓概。
首先我們要注意的是將 Obj C 對象注冊給 window 對象的時機(jī)漾月,由于每次重新載入網(wǎng)頁,window 對象的內(nèi)容都會有所變動-畢竟每個網(wǎng)頁都會有不同的 JS 程序胃珍,所以梁肿,我們需要在適當(dāng)?shù)臅r機(jī)做這件事情蜓陌。我們首先要指定 WebView 的 frame loading delegate(用 setFrameLoadDelegate:),并且實(shí)作 webView:didClearWindowObject:forFrame:吩蔑,WebView 只要更新了 windowScriptObject钮热,就會調(diào)用這一段程序。假如我們現(xiàn)在要讓網(wǎng)頁中的 JS 可以使用目前的 controller 對象烛芬,會這樣寫:
1
2
3
4
(void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame
{
[windowObject setValue:selfforKey:@"controller"];
}(void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame{ [windowObject setValue:selfforKey:@"controller"];}
如此一來隧期,只要調(diào)用 window.controller,就可以調(diào)用我們的 Obj C 對象赘娄。假如我們的 Obj C Class 里頭有這些成員變數(shù):
@interfaceMyController :NSObject
{
IBOutletWebView webView;
IBOUtlet NSWindowwindow;
NSStringstringValue;
NSIntegernumberValue;
NSArrayarrayValue;
NSDatedateValue;
NSDictionarydictValue;
NSRectframeValue;
}
@end
@interfaceMyController :NSObject{ IBOutletWebView webView; IBOUtlet NSWindowwindow; NSStringstringValue; NSIntegernumberValue; NSArrayarrayValue; NSDatedateValue; NSDictionarydictValue; NSRectframeValue;}@end
指定一下 Value:
1
2
3
4
5
6
stringValue =@"string";
numberValue = 24;
arrayValue = [[NSArrayarrayWithObjects:@"text", [NSNumbernumberWithInt:30],nil] retain];
dateValue = [[NSDatedate] retain];
dictValue = [[NSDictionarydictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2",@"value3",@"key3",nil] retain];
frameValue = [window frame];
stringValue =@"string";numberValue = 24;arrayValue = [[NSArrayarrayWithObjects:@"text", [NSNumbernumberWithInt:30],nil] retain];dateValue = [[NSDatedate] retain];dictValue = [[NSDictionarydictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2",@"value3",@"key3",nil] retain];frameValue = [window frame];
用 JS 讀讀看:
01
02
03
04
05
06
07
08
09
10
11
12
varc = window.controller;
varmain = document.getElementById('main');
varHTML ='';
if(c) {
HTML +='<p>'+ c.stringValue +'<p>';
HTML +='<p>'+ c.numberValue +'<p>';
HTML +='<p>'+ c.arrayValue +'<p>';
HTML +='<p>'+ c.dateValue +'<p>';
HTML +='<p>'+ c.dictValue +'<p>';
HTML +='<p>'+ c.frameValue +'<p>';
main.innerHTML = HTML;
}
varc = window.controller;varmain = document.getElementById('main');varHTML ='';if(c) { HTML +='<p>'+ c.stringValue +'<p>'; HTML +='<p>'+ c.numberValue +'<p>'; HTML +='<p>'+ c.arrayValue +'<p>'; HTML +='<p>'+ c.dateValue +'<p>'; HTML +='<p>'+ c.dictValue +'<p>'; HTML +='<p>'+ c.frameValue +'<p>'; main.innerHTML = HTML;}
結(jié)果如下:
string24text,302010-09-09 00:01:04 +0800{ key1 = value1; key2 = value2; key3 = value3; }NSRect: {{275, 72}, {570, 657}}
string24text,302010-09-09 00:01:04 +0800{ key1 = value1; key2 = value2; key3 = value3; }NSRect: {{275, 72}, {570, 657}}
不過仆潮,如果你看完上面的范例,就直接照做遣臼,應(yīng)該不會直接成功出現(xiàn)正確的結(jié)果鸵闪,而是會拿到一堆 undefined,原因是暑诸,Obj C 對象的 Value 預(yù)設(shè)被保護(hù)起來蚌讼,不會讓 JS 直接存取。要讓 JS 可以存取 Obj C 對象的 Value个榕,需要實(shí)作 +isKeyExcludedFromWebScript: 針對傳入的 Key 一一處理篡石,如果我們希望 JS 可以存取這個 key,就回傳 NO:
1
2
3
4
5
6
7
(BOOL)isKeyExcludedFromWebScript:(constchar*)name
{
if(!strcmp(name,"stringValue")) {
returnNO;
}
returnYES;
}(BOOL)isKeyExcludedFromWebScript:(constchar*)name{ if(!strcmp(name,"stringValue")) { returnNO; } returnYES;}
除了可以讀取 Obj C 對象的 Value 外西采,也可以設(shè)定 Value凰萨,相當(dāng)于在 Obj C 中使用 setValue:forKey:,如果在上面的 JS 程序中械馆,我們想要修改 stringValue胖眷,直接調(diào)用 c.stringValue = ‘new value’ 即可。像前面提到霹崎,在這裡傳給 Obj C 的 JS 對象珊搀,除了字串與數(shù)字外,class 都是 WebScriptObject尾菇,空對象是 WebUndefined境析。
※ 用 JavaScript 調(diào)用 Objective C method
Obj C 的語法沿襲自 SmallTalk,Obj C 的 selector派诬,與 JS 的 function 語法有相當(dāng)?shù)牟町惱拖ebKit 預(yù)設(shè)的實(shí)作是,如果我們要在 JS 調(diào)用 Obj C selector默赂,就是把所有的參數(shù)往后面擺沛鸵,并且把所有的冒號改成底線,而原來 selector 如果有底線的話缆八,又要另外處理曲掰。假使我們的 controller 對象有個 method朝刊,在 Obj C 中寫成這樣:
1
(void)setA:(id)a b:(id)b c:(id)c;
(void)setA:(id)a b:(id)b c:(id)c;
在 JS 中就這麼調(diào)用:
[cpp]view plaincopyprint?
controller.setA_b_c_('a','b','c');
controller.setA_b_c_('a','b','c');1
controller.setA_b_c_('a','b','c');
實(shí)在有點(diǎn)丑。所以 WebKit 提供一個方法蜈缤,可以讓我們把某個 Obj C selector 變成好看一點(diǎn)的 JS function。我們要實(shí)作 webScriptNameForSelector:
1
2
3
4
5
6
7
(NSString*)webScriptNameForSelector:(SEL)selector
{
if(selector ==@selector(setA:b:c:)) {
return@"setABC";
}
returnnil;
}(NSString*)webScriptNameForSelector:(SEL)selector{ if(selector ==@selector(setA:b:c:)) { return@"setABC"; } returnnil;}
以后就可以這麼調(diào)用:
1
controller.setABC('a','b','c');
controller.setABC('a','b','c');
我們同樣可以決定哪些 selector 可以給 JS 使用冯挎,哪些要保護(hù)起來底哥,方法是實(shí)作 isSelectorExcludedFromWebScript:。而我們可以改變某個 Obj C selector 在 JS 中的名稱房官,我們也可以改變某個 value 的 key趾徽,方法是實(shí)作 webScriptNameForKey:。
有幾件事情需要注意一下:
用 JavaScript 調(diào)用 Objective C 2.0 的 property
在上面翰守,我們用 JS 調(diào)用 window.controller.stringValue孵奶,與設(shè)定里頭的 value 時,這邊很像我們使用 Obj C 2.0 的語法蜡峰,但其實(shí)做的是不一樣的事情了袁。用 JS 調(diào)用 controller.stringValue,對應(yīng)到的 Obj C 語法是 [controller valueForKey:@"stringValue"]湿颅,而不是調(diào)用 Obj C 對象的 property载绿。
如果我們的 Obj C 對象有個 property 叫做 stringValue,我們知道油航,Obj C property 其實(shí)會在編譯時崭庸,變成 getter/setter method,在 JS 里頭谊囚,我們便應(yīng)該要調(diào)用 controller.stringValue() 與 controller.setStringValue_()怕享。
Javascript 中,F(xiàn)unction 即對象的特性
JS 的 function 是對象镰踏,當(dāng)一個 Obj C 對象的 method 出現(xiàn)在 JS 中時函筋,這個 method 在 JS 中,也可以或多或少當(dāng)做對象處理奠伪。我們在上面產(chǎn)生了 setABC驻呐,也可以試試看把它倒出來瞧瞧:
1
console.log(controller.setABC);
console.log(controller.setABC);
我們可以從結(jié)果看到:
function setABC() { [native code] }
function setABC() { [native code] }
這個 function 是 native code。因?yàn)槭?native code芳来,所以我們無法對這個 function 調(diào)用 call 或是 apply含末。
另外,在把我們的 Obj C 對象注冊成 window.controller 后即舌,我們會許也會想要讓 controller 變成一個 function 來執(zhí)行佣盒,像是調(diào)用 window.controller();或是顽聂,我們就只想要產(chǎn)生一個可以讓 JS 調(diào)用的 function肥惭,而不是整個對象都放進(jìn) JS 里頭盯仪。我們只要在 Obj C 對象中,實(shí)作 invokeDefaultMethodWithArguments:蜜葱,就可以回傳在調(diào)用 window.controller() 時想要的結(jié)果全景。
現(xiàn)在我們可以綜合練習(xí)一下。前面提到牵囤,由于我們可以把 JS 對象以 WebScriptObject 這個 class 傳入 Obj C 程序爸黄,Obj C 程序中也可以要求執(zhí)行 WebScriptObject 的各項(xiàng) function。我們假如想把 A 與 B 兩個數(shù)字丟進(jìn) Obj C 程序里頭做個加法揭鳞,加完之后出現(xiàn)在網(wǎng)頁上炕贵,于是我們寫了一個 Obj C method:
1
2
3
4
5
(void)numberWithA:(id)a plusB:(id)b callback:(id)callback
{
NSIntegerresult = [a integerValue] + [b integerValue];
[callback callWebScriptMethod:@"call"withArguments:[NSArrayarrayWithObjects:callback, [NSNumbernumberWithInteger:result],nil]];
}(void)numberWithA:(id)a plusB:(id)b callback:(id)callback{ NSIntegerresult = [a integerValue] + [b integerValue]; [callback callWebScriptMethod:@"call"withArguments:[NSArrayarrayWithObjects:callback, [NSNumbernumberWithInteger:result],nil]];}
JS 里頭就可以這樣調(diào)用:
1
2
3
4
window.controller.numberWithA_plusB_callback_(1, 2,function(result) {
varmain = document.getElementById('main');
main.innerText = result;
});
window.controller.numberWithA_plusB_callback_(1, 2,function(result) { varmain = document.getElementById('main'); main.innerText = result;});
※ 其他平臺上 WebKit 的實(shí)作
除了 Mac OS X,WebKit 這幾年也慢慢移植到其他的作業(yè)系統(tǒng)與 framework 中野崇,也或多或少都有 Native API 要求 WebView 執(zhí)行 Js称开,以及從 JS 調(diào)用 Native API 的機(jī)制。
跟 Mac OS X 比較起來乓梨,iPhone 上 UIWebView 的公開 API 實(shí)在少上許多鳖轰。想要讓 UIWebView 執(zhí)行一段 JS,可以透過調(diào)用 stringByEvaluatingJavaScriptFromString:扶镀,只會回傳字串結(jié)果脆霎,所以能夠做到的事情也就變得有限,通常大概就拿來取得像 window.title 這些資訊狈惫。在 iPhone 上我們沒辦法將某個 Obj C 對象變成 JS 對象睛蛛,所以,在網(wǎng)頁中觸發(fā)了某些事件胧谈,想要通知 Obj C 這一端忆肾,往往會選擇使用像「zonble://」這類 Customized URL scheme。
ChromeOS 完全以 WebKit 製作使用者介面菱肖,不過我們沒辦法在 ChomeOS 上寫我們在這邊所討論的桌面或行動應(yīng)用程序客冈,所以不在我們討論之列。(順道岔題稳强,ChromeOS 是設(shè)計來給 Netbook 使用的作業(yè)系統(tǒng)场仲,可是像 Toshiba 都已經(jīng)用 Android,做出比 Netbook 更小的 Smartbook退疫,而且應(yīng)用程序更多渠缕,ChromeOS 的產(chǎn)品做出來的話,實(shí)在很像 Google 拿出兩套東西褒繁,自己跟自己對打)亦鳞。
Android 的 WebView 對象提供一個叫做 addJavascriptInterface() 的 method,可以將某個 Java 對象注冊成 JS 的 window 對象的某個屬性,就可以讓 JS 調(diào)用 Java 對象燕差。不過遭笋,在調(diào)用 Java 對象時,只能夠傳遞簡單的文字徒探、數(shù)字瓦呼,複雜的 JS 對象就沒辦法了。而在 Android 上想要 WebView 執(zhí)行一段 JS测暗,在文件中沒看到相關(guān)資料央串,網(wǎng)路上面找到的說法是,可以透過 loadUrl()偷溺,把某段 JS 用 bookmarklet 的形式傳進(jìn)去。
在 QtWebKit 里頭钱贯,可以對 QWebFrame 調(diào)用 addToJavaScriptWindowObject挫掏,把某個 QObject 暴露在 JS 環(huán)境中,我不清楚 JS 可以傳遞哪些東西到 QObject 里頭就是了秩命。在 QtWebKit 中也可以取得網(wǎng)頁里頭的 DOM 對象(QWebElement尉共、QWebElementCollection),我們可以對 QWebFrame 還有這些 DOM 對象調(diào)用 evaluateJavaScript弃锐,執(zhí)行 Javascript袄友。
GTK 方面,因?yàn)槭?C API霹菊,所以在應(yīng)用程序與 JS 之間剧蚣,就不是透過操作包裝好的對象,而是調(diào)用 WebKit 里頭 JavaScript Engine 的 C API旋廷。
※ JavaScriptCore Framework
我們在 Mac OS X 上面鸠按,也可以透過 C API,要求 WebView 執(zhí)行 Javascript饶碘。首先要 import 目尖。如果我們想要簡單改一下 window.location.href:
1
2
3
4
5
JSGlobalContextRef globalContext = [[webView mainFrame] globalContext];
JSValueRef exception = NULL;
JSStringRef script = JSStringCreateWithUTF8CString("window.location.href='http://spring-studio.net'");
JSEvaluateScript(globalContext, script, NULL, NULL, 0, &exception);
JSStringRelease(script);
JSGlobalContextRef globalContext = [[webView mainFrame] globalContext];JSValueRef exception = NULL;JSStringRef script = JSStringCreateWithUTF8CString("window.location.href='http://spring-studio.net'");JSEvaluateScript(globalContext, script, NULL, NULL, 0, &exception);JSStringRelease(script);
如果我們想要讓 WebView 里頭的 JS,可以調(diào)用我們的 C Function:
1
2
3
4
5
6
7
8
(void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame
{
JSGlobalContextRef globalContext = [frame globalContext];
JSStringRef name = JSStringCreateWithUTF8CString("myFunc");
JSObjectRef obj = JSObjectMakeFunctionWithCallback(globalContext, name, (JSObjectCallAsFunctionCallback)myFunc);
JSObjectSetProperty (globalContext, [windowObject JSObject], name, obj, 0,NULL);
JSStringRelease(name);
}(void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame{ JSGlobalContextRef globalContext = [frame globalContext]; JSStringRef name = JSStringCreateWithUTF8CString("myFunc"); JSObjectRef obj = JSObjectMakeFunctionWithCallback(globalContext, name, (JSObjectCallAsFunctionCallback)myFunc); JSObjectSetProperty (globalContext, [windowObject JSObject], name, obj, 0,NULL); JSStringRelease(name);}
那麼扎运,只要 JS 調(diào)用 window.myFunc()瑟曲,就可以取得們放在 myFunc 這個 C function 中回傳的結(jié)果:
1
2
3
4
JSValueRef myFunc(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,size_targumentCount,constJSValueRef arguments[], JSValueRef* exception)
{
returnJSValueMakeNumber(ctx, 42);
}