WKWebView valuta il valore di return di JavaScript

Devo cambiare una function per valutare JavaScript da UIWebView a WKWebView. Devo restituire il risultato della valutazione in questa function.

Ora, sto chiamando:

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

Ma ho bisogno di get il risultato come il valore di return, come in UIWebView . Puoi suggerire una soluzione?

Ho risolto questo problema aspettando il risultato finché non viene restituito il risultato.

Ho usato NSRunLoop per aspettare, ma non sono sicuro che sia il modo migliore o no …

Ecco il codice sorgente di estensione di categoria che sto usando ora.

 @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 

Codice di esempio)

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

Questa soluzione funziona anche se il codice di javascript aumenta 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; } 

Ho appena imbattuto allo stesso problema e ho scritto un po 'di estensione WKWebView di Swift (3.0), pensavo di poterlo condividere:

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

Ho scoperto che il valore dell'istruzione finale nel tuo javascript iniettato è il valore di return passato come argomento id alla function di completamento, se non ci sono eccezioni. Così, per esempio:

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