调用Objective-C函数时将值返回给JavaScript

我一直在使用WebViewJavascriptBridge桥接iOS应用程序中的Objective-C和JavaScript。 它工作的很好,但是它不支持从被调用的本地Objective-C函数返callback用JavaScript代码的值。

我很确定cordova(PhoneGap)以某种方式做callback,但我一直在努力了解底层机制如何工作。

有没有人有同样的问题,并设法find解决scheme?

如果你的意思是,“返回”的意义,你的JS调用者会看到从调用返回的结果,我不知道该怎么做。 我怀疑这将需要在JS中不可用的线程操作级别。 相反,你可以重新编码你的JS端逻辑创build一个结果处理函数。 在伪代码中:

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

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

肯定有点尴尬,但习惯了它 – 这是一个非常普遍的模式。 在内部,JS桥代码创build了请求到callback函数的映射。 当ObjC代码有结果时,它使用WebView的stringByEvaluatingJavaScriptFromString来调用定位和调用callback的JS桥代码。

@Richard – 对你发布的解决scheme要小心点。 设置window.location来调用shouldStartLoadWithRequest可能会导致webview中的function丢失,并且还会将消息丢失到ObjectiveC中。 目前的做法是使用一个iframe,并有一些可以缓冲消息的消息队列。

现在,我从来没有使用过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中执行等价函数要慢得多,因为它必须跳过所有的循环。 但是,如果您的JS代码中已经有ObjC代码需要使用,那么这可能适合您。