![](/img/trans.png)
[英]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.