Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WKWebView evaluate JavaScript return value

I need to change a function to evaluate JavaScript from UIWebView to WKWebView. I need to return result of evaluating in this function.

Now, I am calling:

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

But I need get result like return value, like in UIWebView. Can you suggest a solution?

like image 441
redak105 Avatar asked Nov 06 '14 11:11

redak105


People also ask

What does evaluateJavaScript do?

evaluateJavaScript:inFrame:inContentWorld:completionHandler: Evaluates the specified JavaScript string in the specified frame and content world.

What is WKWebView?

A WKWebView object is a platform-native view that you use to incorporate web content seamlessly into your app's UI. A web view supports a full web-browsing experience, and presents HTML, CSS, and JavaScript content alongside your app's native views.

How do I migrate to WKWebView?

You can implement WKWebView in Objective-C, here is simple example to initiate a WKWebView : WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init]; WKWebView *webView = [[WKWebView alloc] initWithFrame:self. view. frame configuration:theConfiguration]; webView.


2 Answers

Update: This is not working on iOS 12+ anymore.


I solved this problem by waiting for result until result value is returned.

I used NSRunLoop for waiting, but I'm not sure it's best way or not...

Here is the category extension source code that I'm using now:

@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 

Example code:

NSString *userAgent = [_webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];  NSLog(@"userAgent: %@", userAgent); 
like image 75
UnknownStack Avatar answered Sep 22 '22 00:09

UnknownStack


This solution also works if the javascript's code raise 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; } 
like image 32
Brams Avatar answered Sep 24 '22 00:09

Brams