0

I'm using this custom method to parse HTML using a WKWebView:

- (NSString *)stringByEvaluatingJavascript:(NSString *)javascript
{
    NSString *string = @"";

    [self.webView evaluateJavaScript:javascript
               completionHandler:^(id result, NSError *error){

                   if (error) {

                       NSLog(@"Javascript:%@\nError: %@", javascript, error.description);
                   }
                   else {

                       NSString *parsedString = (NSString *)result;

                       NSLog(@"Parsed String: %@", parsedString);

                       __block string = parsedString;
                   }
               }];

    return string;
}

Which I'm using like this:

NSString *count = [self stringByEvaluatingJavascript:@"document.getElementsByTagName('a').length"];

NSLog(@"Count: %@", count);

It logs:

Count:

Parsed String: 242

While I'm getting this warning:

Incompatible pointer to integer conversion initializing 'int' with an expression of type 'NSString *__strong'

How to successfully assign the content of parsedString ("242") to string from within the block?

Vulkan
  • 1,004
  • 16
  • 44

1 Answers1

1

The method that you described in this question should not return any value because the string variable will be initialized in completionHandler of evaluateJavaScript. You should use this method:

- (void)stringByEvaluatingJavascript:(NSString *)javascript
                   completionHandler:(void(^)(NSString*))completionHandlerForEvaluateJS {
    [self.webView evaluateJavaScript:javascript
                   completionHandler:^(id result, NSError *error) {
        if (error) {
            NSLog(@"Javascript:%@\nError: %@", javascript, error.description);
            completionHandlerForEvaluateJS(nil);
        } else {
            NSString *parsedString = (NSString *)result;
            NSLog(@"Parsed String: %@", parsedString);
            completionHandlerForEvaluateJS(parsedString);
        }
    }];
}

How to call it:

[self stringByEvaluatingJavascript:@"document.getElementsByTagName('a').length" completionHandler:^(NSString *count) {
    NSLog(@"Count: %@", count);
}];

And about this error:

Incompatible pointer to integer conversion initializing 'int' with an expression of type 'NSString *__strong'

You get it because __block string is a short form for int __block string.

Roman Podymov
  • 4,168
  • 4
  • 30
  • 57
  • I'd suggesting passing `nil` to the completion handler if there is an error since an empty string might be a valid result. – rmaddy Oct 28 '18 at 21:31
  • @rmaddy It is a very good idea, but as I understood `stringByEvaluatingJavascript` should never return `nil`. – Roman Podymov Oct 28 '18 at 21:35
  • Exactly. That's why you should use `completionHandlerForEvaluateJS(nil);` inside `if (error) {`. This way the caller knows there was an error and not just an empty result. – rmaddy Oct 28 '18 at 21:37