JS交互

1     原理

在寫 JavaScript 的時候,可以使用一個叫做 window 的對象,像是我們想要從現在的網頁跳到另外一個網頁的時候,就會去修改 window.location.href 的位置;在我們的 Objective-C 程序碼中,如果我們可以取得指定的 WebView 對象,也就可以拿到這個出現在 JavaScript 中的 window 對象,也就是 [webView windowScriptObject]。

這個對象就是 WebView 裏頭的 JS 與我們的 Objective-C程序之間的橋樑——window 對象可以取得網頁裏頭所有的 JS 函數與對象,而如果我們把一個 Objective-C 對象設定成 windowScriptObject 的 value,JS 也便可以調用Objective-C對象的 method。於是,我們可以在Objective-C 程序裏頭要求 WebView 執行一段 JS,也可以反過來讓 JS 調用一段用 Obj C 實現的功能。

由於Objective-C 與 JS 本身的語言特性不同,在兩種語言之間相互傳遞東西之間,就可以看到兩者的差別:

  • JS 雖然是 OO,但是並沒有 class,所以將 JS 對象傳到 Obj C 程序裏頭,除了基本字串會轉換成 NSString、基本數字會轉成 NSNumber,像是 Array 等其他對象,在 Objective-C 中,都是 WebScriptObject 這個 Class。意思就是,JS 的 Array 不會幫你轉換成 NSArray。
  • 從 JS 裏頭傳一個空對象給 Objective-C 程序,用的不是 Objective-C 裏頭原本表示「沒有東西」的方式,像是 NULL、nil、NSNull 等,而是專屬 WebKit 使用的 WebUndefined。

2     具體技巧

2.1     用Objective-C 取得與設定JavaScript 對象

要從 Objective-C取得網頁中的 JavaScript 對象,也就是對 windowScriptObject 做一些 KVC 調用,像是 valueForKey: 與 valueForKeyPath:。如果我們在 JS 裏頭,想要知道目前的網頁位置,會這麼寫:

var location = window.location.href;

用 Objective-C 就可以這麼調用:

NSString *location = [[webView windowScriptObject] valueForKeyPath:@"location.href"];

如果我們要設定 window.location.href,要求開啓另外一個網頁,在 JS 裏頭:

window.location.href = 'http://spring-studio.net';

在Objective-C:

[[webView windowScriptObject] setValue:@"http://spring-studio.net"forKeyPath:@"location.href"];

2.2     用Objective C 調用 JavaScript function

2.2.1 用 evaluateWebScript: 執行

要用 Objective-C 調用網頁中的 JS function,大概有幾種方法。第一種是直接寫一段跟你在網頁中會撰寫的 JS 一模一樣的程序,叫 windowScriptObject 用 evaluateWebScript: 執行。

例如,我們想要在網頁中產生一個新的 JS function,內容是:

function x(x) {

return x + 1;

}

 

所以在 Objective-C 中可以這樣寫;

[[webView windowScriptObject] evaluateWebScript:@"function x(x) { return x + 1;}"];

接下來我們就可以調用 window.x():

NSNumber *result = [[webView windowScriptObject] evaluateWebScript:@"x(1)"];

NSLog(@"result:%d", [result integerValue]); // Returns 2

2.2.2 用function對象WebScriptObject執行自己

由於在 JS 中,每個 funciton 其實都是對象,所以我們還可以直接取得 window.x 叫這個對象執行自己。

在 JS 裏頭如果這樣寫:

window.x.call(window.x, 1);

Objective-C 中便是這樣:

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

NSNumber *result = [x callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:x, [NSNumbernumberWithInt:1], nil]];

 

這種讓某個 WebScriptObject 自己執行自己的寫法,其實比較不會用於從 Objective-C 調用 JS 這一端,而是接下來會提到的,由 JS 調用 Objective-C,因爲這樣 JS 就可以把一個 callback function 送到 Objective-C 程序裏頭。

 

2.2.3 利用DOM對象

WebKit 裏頭,所有的 DOM 對象都繼承自 DOMObject,DOMObject 又繼承自 WebScriptObject,所以我們在取得了某個 DOM 對象之後,也可以從 Objective-C 程序中,要求這個 DOM 對象執行 JS 程序。

假如我們的網頁中,有一個 id 叫做 “#s” 的文字輸入框(text input),而我們希望現在鍵盤輸入的焦點放在這個輸入框上,在 JS 裏頭會這樣寫:

document.querySelector('#s').focus();

在Objective-C中寫法:

DOMDocument *document = [[webView mainFrame] DOMDocument];

[[document querySelector:@"#s"] callWebScriptMethod: @"focus"withArguments:nil];

 

2.3     用JavaScript存取Objective-C的Value

要讓網頁中的 JS 程序可以調用 Objective-C 對象,方法是把某個 Objective-C 對象註冊成 JS 中 window 對象的屬性。之後,JS 便也可以調用這個對象的 method,也可以取得這個對象的各種 Value,只要是 KVC 可以取得的 Value,像是 NSString、NSNumber、NSDate、NSArray、NSDictionary、NSValue…等。JS 傳 Array 到 Objective-C 時,還需要做些特別處理才能變成 NSArray,從 Obj C 傳一個 NSArray 到 JS 時,會自動變成 JS Array。

2.3.1 將Objective-C對象註冊給window對象的時機

首先我們要注意的是將 Objective-C 對象註冊給 window 對象的時機,由於每次重新載入網頁,window 對象的內容都會有所變動-畢竟每個網頁都會有不同的 JS 程序,所以,我們需要在適當的時機做這件事情。我們首先要指定 WebView 的 frame loading delegate(用 setFrameLoadDelegate:),並且實現 webView:didClearWindowObject:forFrame:,WebView 只要更新了 windowScriptObject,就會調用這一段程序。

假如我們現在要讓網頁中的 JS 可以使用目前的 controller 對象,會這樣寫:

- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame

{

[windowObject setValue:self forKey:@"controller"];

}

如此一來,只要調用 window.controller,就可以調用我們的 Objective-C 對象。

2.3.2 JS中存取 Objective-C 對象的 Value

假如我們的 Objective-C Class 裏頭有這些成員變量:

@interface MyController : NSObject

{

IBOutlet WebView *webView;

IBOUtlet  NSWindow *window;

NSString *stringValue;

NSInteger numberValue;

NSArray *arrayValue;

NSDate *dateValue;

NSDictionary *dictValue;

NSRect frameValue;

}

@end

 

指定一下 Value:

stringValue = @"string";

numberValue = 24;

arrayValue = [[NSArray arrayWithObjects:@"text", [NSNumbernumberWithInt:30], nil] retain];

dateValue = [[NSDate date] retain];

dictValue = [[NSDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1", @"value2", @"key2", @"value3", @"key3", nil] retain];

frameValue = [window frame];

 

用 JS 讀讀看:

var c = window.controller;

var main = document.getElementById('main');

var HTML = '';

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;

}

結果如下:

string 24 text,30 2010-09-09 00:01:04 +0800 { key1 = value1; key2 = value2; key3 = value3; } NSRect: {{275, 72}, {570, 657}}

不過,如果你看完上面的範例,就直接照做,應該不會直接成功出現正確的結果,而是會拿到一堆 undefined,原因是,Objective-C 對象的 Value 預設被保護起來,不會讓 JS 直接存取。要讓 JS 可以存取 Objective-C 對象的 Value,需要操作 +isKeyExcludedFromWebScript: 針對傳入的 Key 一一處理,如果我們希望 JS 可以存取這個 key,就回傳 NO:

+ (BOOL)isKeyExcludedFromWebScript:(const char *)name

{

if (!strcmp(name, "stringValue")) {

return NO;

}

return YES;

}

除了可以讀取 Objective-C對象的 Value 外,也可以設定 Value,相當於在 Objective-C中使用 setValue:forKey:,如果在上面的 JS 程序中,我們想要修改 stringValue,直接調用 c.stringValue = ‘new value’ 即可。像前面提到,在這裡傳給 Objective-C的 JS 對象,除了字串與數字外,class 都是 WebScriptObject,空對象是 WebUndefined。

2.4     用 JavaScript調用 Objective-C方法

2.4.1 方法寫法差異

Objective-C 的語法沿襲自 SmallTalk,Objective-C 的 selector,與 JS 的 function 語法有相當的差異。WebKit 預設的實事是,如果我們要在 JS 調用 Objective-C selector,就是把所有的參數往後面擺,並且把所有的冒號改成底線,而原來 selector 如果有底線的話,又要另外處理。

假使我們的 controller 對象有個 method,在 Objective-C 中寫成這樣:

- (void)setA:(id)a b:(id)b c:(id)c;

在 JS 中就這麼調用:

controller.setA_b_c_('a', 'b', 'c');

2.4.2  給方法取別名

實在有點醜。所以 WebKit 提供一個方法,可以讓我們把某個 Objective-C selector 變成好看一點的 JS function。我們要實現 webScriptNameForSelector:

+ (NSString *)webScriptNameForSelector:(SEL)selector

{

if (selector == @selector(setA:b:c:)) {

return @"setABC";

}

return nil;

}

以後就可以這麼調用:

controller.setABC('a', 'b', 'c');

我們同樣可以決定哪些 selector 可以給 JS 使用,哪些要保護起來,方法是實作 isSelectorExcludedFromWebScript:。而我們可以改變某個 Objective-C selector 在 JS 中的名稱,我們也可以改變某個 value 的 key,方法是實作 webScriptNameForKey:。

2.4.3 注意

有幾件事情需要注意一下:

用 JavaScript 調用 Objective C 2.0 的 property。在上面,我們用 JS 調用 window.controller.stringValue,與設定裏頭的 value 時,這邊很像我們使用 Objective-C 2.0 的語法,但其實做的是不一樣的事情。用 JS 調用 controller.stringValue,對應到的 Objective-C 語法是 [controller valueForKey:@"stringValue"],而不是調用 Objective-C 對象的 property。

 

如果我們的 Objective-C 對象有個 property 叫做 stringValue,我們知道,Objective-C property 其實會在編譯時,變成 getter/setter method,在 JS 裏頭,我們便應該要調用 controller.stringValue() 與 controller.setStringValue_()。

 

Javascript 中,Function 即對象的特性

JS 的 function 是對象,當一個 Objective-C 對象的 method 出現在 JS 中時,這個 method 在 JS 中,也可以或多或少當做對象處理。我們在上面產生了 setABC,也可以試試看把它倒出來瞧瞧:

console.log(controller.setABC);

我們可以從結果看到:

 

function setABC() { [native code] }

這個 function 是 native code。因爲是 native code,所以我們無法對這個 function 調用 call 或是 apply。

 

另外,在把我們的 Objective-C 對象註冊成 window.controller 後,我們會許也會想要讓controller變成一個 function 來執行,像是調用 window.controller();或是,我們就只想要產生一個可以讓 JS 調用的 function,而不是整個對象都放進 JS 裏頭。我們只要在 Objective-C 對象中,實現invokeDefaultMethodWithArguments:,就可以回傳在調用 window.controller() 時想要的結果。

2.4.4 示例

現在我們可以綜合練習一下。前面提到,由於我們可以把 JS 對象以 WebScriptObject 這個 class 傳入 Obj C 程序,Objective-C 程序中也可以要求執行 WebScriptObject 的各項 function。我們假如想把 A 與 B 兩個數字丟進 Objective-C 程序裏頭做個加法,加完之後出現在網頁上,於是我們寫了一個 Objective-C method:

- (void)numberWithA:(id)a plusB:(id)b callback:(id)callback

{

NSInteger result = [a integerValue] + [b integerValue];

[callback callWebScriptMethod:@"call" withArguments:[NSArrayarrayWithObjects:callback, [NSNumber numberWithInteger:result],nil]];

}

JS 裏頭就可以這樣調用:

window.controller.numberWithA_plusB_callback_(1, 2,function(result) {

var main = document.getElementById('main');

main.innerText = result;

});

3     WebViewJavascriptBridge橋接庫

WebViewJavascriptBridge

https://github.com/marcuswestin/WebViewJavascriptBridge

 

3.1     機制原理

很明顯:WebViewJavascriptBridge.js.txt主要用於銜接UIWebView中的web page,而WebViewJavascriptBridge.h/m則主要用於與ObjC的nativecode打交道。他們作爲一個整體,其實起到了一個“橋樑”的作用,這三個文件封裝了他們具體的交互處理方式,只開放出一些對外的涉及到業務處理的API,因此你在需要UIWebView與Nativecode交互的時候,引入該庫,則無需考慮太多的交互上的問題。整個的Bridge對你來說都是透明的,你感覺編程的時候,就像是web編程的前端和後端一樣清晰。

3.1.1 Native端工作機制

Native端中主要工作機制是,將當前WebView的Delegate截留,用當前Bridge實例對象作爲委託Target對象,獲取到WebViewDelegate回調方法(主要在shouldStartLoadWithRequest回調方法中進行橋接處理)並加以處理後,再往上回調到目標VC中;具體代碼如下所示:

- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(id<UIWebViewDelegate>)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle{

_messageHandler = messageHandler;

_webView = webView;

_webViewDelegate = webViewDelegate;

_messageHandlers = [NSMutableDictionary dictionary];

_webView.delegate = self;

_resourceBundle = bundle;

}

 

回調上層方法示例:

__strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;

if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {

[strongDelegate webViewDidFinishLoad:webView];

}

 

3.1.2 Native端事件解析處理機制

Js端需要傳遞的業務數據並不通過Url參數傳遞,而是通過在Native端調用js方法直接獲取數據JSON對象,再將其做解析處理。集中在- (void)_flushMessageQueue方法中處理。核心代碼如下:

 

//1、獲取業務數據JSON對象字符串

NSString *messageQueueString = [_webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"];

//2、將對象序列化爲數組

id messages = [self _deserializeMessageJSON:messageQueueString];

//3、枚舉每個Message對象並作解析處理

NSString* responseId = message[@"responseId"];

if (responseId) {

WVJBResponseCallback responseCallback = _responseCallbacks [responseId];

responseCallback(message[@"responseData"]);

[_responseCallbacks removeObjectForKey:responseId];

} else {

WVJBResponseCallback responseCallback = NULL;

NSString* callbackId = message[@"callbackId"];

if (callbackId) {

responseCallback = ^(id responseData) {

if (responseData == nil) {

responseData = [NSNull null];

}

 

WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData };

[self _queueMessage:msg];

};

} else {

responseCallback = ^(id ignoreResponseData) {

// Do nothing

};

}

 

WVJBHandler handler;

if (message[@"handlerName"]) {

handler = _messageHandlers[message[@"handlerName"]];

} else {

handler = _messageHandler;

}

 

///!!!在此完成註冊事件回調,包括註冊事件與接收數據事件

handler(message[@"data"], responseCallback);

}

 

3.1.3 js端工作機制

js端通過iFrame來觸發一次load動作,但是iFrame本身的Url並不攜帶數據,而僅僅是用於觸發load動作,具體的業務數據緩存在sendMessageQueue數組中。

Native端捕獲到load動作後,再調用window.WebViewJavascriptBridge類的_fetchQueue()方法獲取業務數據去做解析。

所以,js端作用主要有三個:

  • 緩存業務數據(包括註冊事件);
  • 提供公用方法供Native端調用,一般用於獲取緩存的業務數據;
  • 觸發load動作以喚醒與Native的交互動作;

 

主要公用方法:

handleMessageFromObjC方法

用於供Native端發送數據到js端;

 

fetchQueue方法:

用於供Native端獲取業務數據對象;

 

registerHandler(handlerName, handler)方法

用於註冊js事件方法,用於供Native端調用;

callHandler(handlerName, data, responseCallback)方法

用於調用Native端事件方法。

3.2     功能特性

【1】UI端

(1)UI端在初始化時支持設置消息的默認處理器(這裏的消息指的是從Native端接收到的消息);

(2)從UI端向Native端發送消息,並支持對於Native端響應後的回調處理的定義;

(3)UI端調用Native定義的處理器,並支持Native端響應後的回調處理定義;

(4)UI端註冊處理器(供Native端調用),並支持給Native端響應處理邏輯的定義;

【2】Native端

(1)Native端在初始化時支持設置消息的默認處理器(這裏的消息指的是從UI端發送過來的消息);

(2)從Native端向UI端發送消息,並支持對於UI端響應後的回調處理邏輯的定義;

(3)Native端調用UI端定義的處理器,並支持UI端給出響應後在Native端的回調處理邏輯的定義;

(4)Native端註冊處理器(供UI端調用),並支持給UI端響應處理邏輯的定義UI端以及Native端完全是對等的兩端,實現也是對等的。一段是消息的發送端,另一段就是接收端。這裏爲引起混淆,需要解釋一下我這裏使用的“響應”、“回調”在這個上下文中的定義:

(1)響應:接收端給予發送端的應答

(2)回調:發送端收到接收端的應答之後在接收端調用的處理邏輯

3.3     使用過程

1.初始化一個webview(viewdidload)

UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.bounds];

[self.view addSubview:webView];

2.將此webview與WebViewJavascriptBridge關聯(viewdidload)

if (_bridge) { return; }

[WebViewJavascriptBridge enableLogging];

_bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) {

NSLog(@"ObjC received message from JS: %@", data);

responseCallback(@"Response for message from ObjC");

}];

ps:此時你的webview就與js搭上橋了。下面就是方法的互調和參數的互傳。

(1) js調oc方法(可以通過data給oc方法傳值,使用responseCallback將值再返回給js)

[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {

NSLog(@"testObjcCallback called: %@", data);

responseCallback(@"Response from testObjcCallback");

}];

這裏注意testObjcCallback這個方法的標示。html那邊的命名要跟ios這邊相同,才能調到這個方法。當然這個名字可以兩邊商量着自定義。簡單明確即可。

(2)oc調js方法(通過data可以傳值,通過 response可以接受js那邊的返回值 )

id data = @{ @"greetingFromObjC": @"Hi there, JS!" };

[_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) {

NSLog(@"testJavascriptHandler responded: %@", response);

}];

注意這裏的 testJavascriptHandler也是個方法標示。

(3)oc給js傳值(通過 response接受返回值 )

[_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) {

NSLog(@"sendMessage got response: %@", response);

}];

(4)oc給js傳值(無返回值)

[_bridge send:@"A string sent from ObjC after Webview has loaded."];

3.4     JS端使用

3.4.1 初始化示例代碼

function connectWebViewJavascriptBridge(callback) {

if (window.WebViewJavascriptBridge) {

callback(WebViewJavascriptBridge)

} else {

//以事件監聽器形式註釋初始化方法

document.addEventListener('WebViewJavascriptBridgeReady', function() {

callback(WebViewJavascriptBridge)

}, false)

}

}

 

connectWebViewJavascriptBridge(function(bridge) {

var uniqueId = 1

function log(message, data) {

var log = document.getElementById('log')

var el = document.createElement('div')

el.className = 'logLine'

el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)

if (log.children.length) { log.insertBefore(el, log.children[0]) }

else { log.appendChild(el) }

}

//調用對象Init初始化方法完成Bridge對象自身的初始化動作

bridge.init(function(message, responseCallback) {

log('JS got a message', message)

var data = { 'Javascript Responds':'Wee!' }

log('JS responding with', data)

responseCallback(data)

})

//註冊一些事件,供Native端調用

bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {

log('ObjC called testJavascriptHandler with', data)

var responseData = { 'Javascript Says':'Right back atcha!' }

log('JS responding with', responseData)

responseCallback(responseData)

})

})

3.4.2 註冊事件供Native調用

//註冊一些事件,供Native端調用

bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {

log('ObjC called testJavascriptHandler with', data)

var responseData = { 'Javascript Says':'Right back atcha!' }

log('JS responding with', responseData)

responseCallback(responseData)

})

3.4.3 UI事件發送數據到Native

var button = document.getElementById('buttons').appendChild(document.createElement('button'))

button.innerHTML = 'Send message to ObjC'

button.onclick = function(e) {

e.preventDefault()

var data = 'Hello from JS button'

log('JS sending message', data)

bridge.send(data, function(responseData) {

log('JS got response', responseData)

})

}

document.body.appendChild(document.createElement('br'))

3.4.4 UI事件調用Native註冊方法

var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button'))

callbackButton.innerHTML = 'Fire testObjcCallback'

callbackButton.onclick = function(e) {

e.preventDefault()

log('JS calling handler "testObjcCallback"')

bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) {

log('JS got response', response)

})

}

3.5     Native端使用

3.5.1 初始化

建議在ViewDidLoad中完成

_bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) {

NSLog(@"ObjC received message from JS: %@", data);

responseCallback(@"Response for message from ObjC");

}];

3.5.2 註冊事件方法供JS調用

[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {

NSLog(@"testObjcCallback called: %@", data);

responseCallback(@"Response from testObjcCallback");

}];

3.5.3 發送數據到JS端

[_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) {

NSLog(@"objc got response! %@", responseData);

}];

3.5.4 調用JS中方法

[_bridge callHandler:@"testJavascriptHandler" data: @{ @"foo":@"before ready" }];

4     原生+h5頁面的APP業務解決方案設想

4.1     js端調用APP方法

WebViewJavascriptBridge支持主動發送數據與調用Native已註冊事件方法來與Native端交互。

兩種機制各有所長,不過爲了保證向後兼容性,建議主要採用主動發送數據的方法來實現與Native端的交互。儘量將UI端的業務抽象、歸類,以命令碼+子命令碼+參數數據的形式,封裝到JSON對象中,傳遞到Native端,Native端的解析邏輯統一採用一個引擎類來集中處理。

這樣也利於IOS與Android兩個平臺的邏輯統一。

以集成微信支付爲例:

因爲支付SDK只能用原生端接口,所以可以考慮將各種js端支付操作(發起微信支付、領取卡券等)抽象化成不同類型的命令,用戶點擊頁面“支付”按鈕時,h5頁面發送支付命令到Native端,Native將命令進行解析後,調起微信SDK中支付接口完成支付,獲取到支付結果後再將結果回調給h5頁面。 

因爲這類APP是以信息展示爲主的APP,各類商品展示頁面肯定會繼續使用h5頁面,但是涉及到與Native端交互時,就需要一個統一的橋接層來處理各類業務操作,就不要使用各種封裝具體某類Native端功能的第三方庫了,總的設計思想應該是設計一個統一的橋接層,然後基於此來統一封裝Native端的各種能力,這一方面,微信是這麼做的、美居也是這麼做的。

4.2     APP端調用js方法

APP端調用js方法,建議也採用同樣策略,制定一個相互調用規範,明確命令編碼,採用json對象傳遞對象數據。不過App端可提供部分註冊方法,供js端來獲取APP端通用信息,例如獲取設備信息、尺寸屏幕的。

5    參考文檔

(good)iOS js與objective-c的交互(轉)

http://www.cnblogs.com/taintain1984/p/3710982.html

(good)iOS 獲取UIWebView上面的按鈕點擊事件

http://blog.csdn.net/zhangkongzhongyun/article/details/24314007

UIWebView的使用總結——js事件交互

http://blog.csdn.net/iunion/article/details/7963291

UIWebView的點擊事件——添加手勢

http://www.cnblogs.com/jauntlin/archive/2011/08/20/2146389.html

WebViewJavascriptBridge

https://github.com/marcuswestin/WebViewJavascriptBridge

(Good)優秀開源代碼解讀:JS與iOS Native Code互調實現方法

http://news.ipadown.com/13212

WebViewJavascriptBridge使用說明(IOS)

http://www.tuicool.com/articles/zuInEn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章