[英]How to get return values when calling Objective-C functions from Javascript?
[英]Returning values to JavaScript when calling an Objective-C function
我一直在使用WebViewJavascriptBridge在 iOS 應用程序中連接 Objective-C 和 JavaScript。 它工作得很好,但它不支持從被調用的本機 Objective-C 函數返回值給調用 JavaScript 代碼。
我很確定 Cordova (PhoneGap) 在某種程度上通過回調做到了這一點,但我一直很難理解底層機制是如何工作的。
有沒有人遇到同樣的問題並設法找到解決方案?
現在,我從未使用過 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;
}
}
我的頁面.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>
視圖控制器.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 中執行等效功能要慢得多,因為它必須跳過所有循環。 但是,如果您需要在您的 JS 代碼中使用已經在您的 ObjC 代碼中的東西,那么這可能適合您。
如果您的意思是“返回”,因為您的 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 並擁有某種可以緩沖消息的消息隊列。
WebViewJavascriptBridge
很久沒有維護了。
也許你應該改用這個庫。
self.bridge.consolePipeBlock = ^(id _Nonnull water) {
NSLog(@"Next line is javascript console.log------>>>>");
NSLog(@"%@",water);
};
這可以很容易地得到javascript console.log。
也有 Swift 語言版本。
bridge.consolePipeClosure = { water in
guard let jsConsoleLog = water else {
print("Javascript console.log give native is nil!")
return
}
print("Next line is Javascript console.log----->>>>>>>")
print(jsConsoleLog)
}
還為您的合作伙伴提供 h5 演示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.