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); } }];