WKWebView评估JavaScript返回值

我需要改变一个函数来评估JavaScript从UIWebView到WKWebView。 我需要在这个函数中返回评估结果。

现在,我打电话给:

[wkWebView evaluateJavaScript:call completionHandler:^(NSString *result, NSError *error) { NSLog(@"Error %@",error); NSLog(@"Result %@",result); }]; 

但是我需要得到像返回值一样的结果,就像在UIWebView 。 你能提出一个解决scheme吗?

我通过等待结果解决了这个问题,直到返回结果值。

我用NSRunLoop等待,但我不知道这是最好的方式或不…

这里是我现在使用的类别扩展源代码。

 @interface WKWebView(SynchronousEvaluateJavaScript) - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; @end @implementation WKWebView(SynchronousEvaluateJavaScript) - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script { __block NSString *resultString = nil; __block BOOL finished = NO; [self evaluateJavaScript:script completionHandler:^(id result, NSError *error) { if (error == nil) { if (result != nil) { resultString = [NSString stringWithFormat:@"%@", result]; } } else { NSLog(@"evaluateJavaScript error : %@", error.localizedDescription); } finished = YES; }]; while (!finished) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } return resultString; } @end 

示例代码)

 NSString *userAgent = [_webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; NSLog(@"userAgent: %@", userAgent); 

这个解决scheme也适用于JavaScript的代码引发NSError:

 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script { __block NSString *resultString = nil; __block BOOL finished = NO; [self evaluateJavaScript:script completionHandler:^(id result, NSError *error) { if (error == nil) { if (result != nil) { resultString = [NSString stringWithFormat:@"%@", result]; } } else { NSLog(@"evaluateJavaScript error : %@", error.localizedDescription); } finished = YES; }]; while (!finished) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } return resultString; } 

我只是偶然发现了同样的问题,并为它写了一个Swift(3.0)WKWebView扩展,以为我可以分享它:

 extension WKWebView { func evaluate(script: String, completion: (result: AnyObject?, error: NSError?) -> Void) { var finished = false evaluateJavaScript(script) { (result, error) in if error == nil { if result != nil { completion(result: result, error: nil) } } else { completion(result: nil, error: error) } finished = true } while !finished { RunLoop.current().run(mode: .defaultRunLoopMode, before: Date.distantFuture) } } } 

我发现在你注入的javascript中final语句的值是作为完成函数的idparameter passing的返回值,如果没有例外的话。 所以,例如:

 [self.webview evaluateJavaScript:@"var foo = 1; foo + 1;" completionHandler:^(id result, NSError *error) { if (error == nil) { if (result != nil) { NSInteger integerResult = [result integerValue]; // 2 NSLog(@"result: %d", integerResult); } } else { NSLog(@"evaluateJavaScript error : %@", error.localizedDescription); } }];