2012-09-12 18 views
3

我一直在使用WebViewJavascriptBridge在iOS應用程序中橋接Objective-C和JavaScript。它工作的很好,但它不支持從被調用的本機Objective-C函數返回調用JavaScript代碼的值。調用Objective-C函數時將值返回到JavaScript

我很確定科爾多瓦(PhoneGap)以某種方式做回調,但我一直在試圖瞭解底層機制如何工作。

有沒有人遇到同樣的問題,並設法找到解決方案?現在

回答

2

如果你的意思是,「返回」的意義上,你的JS調用者將看到從調用返回的結果,我不知道該怎麼做。我懷疑這將需要一定程度的線程操作在JS中不可用。相反,你可以重新編碼你的JS端邏輯來創建一個結果處理函數。在僞代碼:

res = CallObjC(args); 
work with res... 

變爲

CallObjC(args, function(res) { work with res...}); 

誠然有點彆扭,但習慣了就好了 - 這是一個很常見的模式。在內部,JS橋代碼創建請求到回調函數的映射。當ObjC代碼有結果時,它使用WebView的stringByEvaluatingJavaScriptFromString調用定位並調用回調的JS橋代碼。

@Richard - 對您發佈的解決方案要小心。設置window.location來調用shouldStartLoadWithRequest可能會導致webview中的功能丟失,並且還會將消息丟失到ObjectiveC。目前的做法是使用一個iframe,並有一些可以緩衝消息的消息隊列。

+0

你會如何寫這兩個參數?當我運行這個函數時,我得到了太多參數的錯誤。 – Dagrooms

+0

應該可能會用您的代碼創建一個新問題,以及發生錯誤的時間和位置。 – DrC

4

,我從來沒有用過WebViewJavascriptBridge,但我一直在使用一個簡單的委託在Objective-C做到了這一點,所以也許這將幫助你:

MyScript.js

// requestFromObjc 
// functionName (required): 
//  the name of the function to pass along to objc 
// returnedResult (not used by caller): 
//  the result given by objc to be passed along 
// callback (not used by caller): 
//  sent by objc, name of the function to execute 
function requestFromObjc(functionName, objcResult, callback) 
{  
    if (!objcResult) 
    { 
     window.location = "myapp://objcRequest?function=" + functionName + "&callback=" + arguments.callee.name + "&callbackFunc=" + arguments.callee.caller.name; 
    } 
    else 
    { 
     window[callback](objcResult); 
    } 
} 

function buttonClick(objcResult) 
{  
    if (!objcResult) 
    { 
     // ask for the color from objc 
     requestFromObjc("buttonColor&someParam=1"); 
    } 
    else 
    { 
     // do something with result (in this case, set the background color of my div) 
     var div = document.getElementById("someDiv"); 

     div.style.background = objcResult; 
    } 
} 

的mypage.html

<html> 
    <head> 
     <script type="text/javascript" src="MyScript.js"></script> 
    </head> 
    <body> 
     <div id="someDiv"> 
      This is my div! Do not make fun of it, though. 
     </div> 

     <button onClick="buttonClick(undefined)"> 
      Click Me! 
     </button> 
    </body> 
</html> 

ViewController.m

-(NSString *) javaScriptResultForRequest:(NSDictionary *) params 
{ 
    if ([params[@"function"] isEqualToString:@"buttonColor"]) 
    { 
     NSArray *colors = @[ @"red", @"yellow", @"blue", @"green", @"purple" ]; 
     return colors[arc4random_uniform(colors.count)]; 
    } 
    else 
    { 
     return @"undefined"; 
    } 
} 

-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{ 
    if ([[[request URL] scheme] isEqualToString:@"myapp"]) 
    { 
     // parse the URL here 
     NSURL *URL = [request URL]; 

     if ([URL.host isEqualToString:@"objcRequest"]) 
     { 
      NSMutableDictionary *queryParams = [NSMutableDictionary dictionary]; 
      NSArray *split = [URL.query componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"&="]]; 

      for (int i = 0; i < split.count; i += 2) 
      { 
       queryParams[split[i]] = split[i + 1]; 
      } 

      NSString *result = [self javaScriptResultForRequest:queryParams]; 
      NSString *jsRequest = [NSString stringWithFormat:@"%@(\"%@\", \"%@\", \"%@\")", queryParams[@"callback"], queryParams[@"function"], result, queryParams[@"callbackFunc"]]; 

      // now we send this to the target 
      [self.webView stringByEvaluatingJavaScriptFromString:jsRequest]; 
      return NO; 
     } 
    } 

    return YES; 
} 

顯然,這是不是試圖做相同功能的純JS慢得多,因爲所有的迴路有跳通過。但是,如果您需要在您的ObjC代碼中的JS代碼中使用某些內容,則可能適用於您。

相關問題