真的就是亂寫用的筆記

如果我們想要讓我們的 controller object 與 webView 裡頭的 Javascript 溝通,其中一個關鍵就是 WebView 的 -(id)windowScriptObject。我們這邊先講從 ObjC 送東西到網頁裡頭,或是從 ObjC抓網頁裡頭的東西,先不談怎麼從 JS 送東西到 ObjC。

簡單講,在 Javascript 裡頭,有一個物件叫做 window,而這個物件在 ObjC 中,就是 [webView windowScriptObject]。在 JS 裡頭,如果沒有特別定義,直接寫一個簡單的 function,這個 function 其實就會變成 window 的成員。回到前一篇的 JS code

function x(x) {
	return x + 1;
}

其實意思就是:

window.x = function(x) {
	return x + 1;
}

而其實這整段 function 都是一個物件,在 ObjC 中,我們如果想要拿 window.x ,就會拿到一個代表 window.x 的 WebScriptObject。而要拿 window.x,就是拿 windowScriptObject 的一個叫做 x 的屬性,所以我們這麼寫:

WebScriptObject *xobj = [[webView windowScriptObject] valueForKey:@"x"];

如果我們想要執行 x (也就是呼叫 x(),或 window.x()),有兩種方法,一種是要求 windowScriptObject 執行叫做 x 的 method,像是這麼寫:

result = [[webView windowScriptObject] callWebScriptMethod:@"x" withArguments:[NSArray arrayWithObjects:[NSNumber numberWithInt:1], nil]];
NSLog(@"result:%@", result);

這段 code 相當於在 JS 中呼叫 window.x(1),注意,數字要包裝成 NSNumber 傳過去。另外一種方法是,我們直接先去拿 window.x 這個 WebScriptObject,然後由這個物件執行自己(對,JS 的 function 本身就是物件,所以可以先用物件的方式拿,然後物件自己執行自己),我們可以用 apply 或是 call。在 JS 裡頭是這樣:

x.apply(x, [1]); 
x.call(x, 1);

ObjC 裡頭就會變成這樣:

id result = [x callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:x, [NSNumber numberWithInt:1], nil]];
id result = [x callWebScriptMethod:@"apply" withArguments:[NSArray arrayWithObjects:x,  [NSArray arrayWithObject:[NSNumber numberWithInt:1]], nil]];

話說 Javascript 這個語言真是哭么的難懂。

1 year ago