如何验证给定时间 WebView 是否执行 JS 代码?

How to verify that a given time WebView performs JS-code?

这是一个 Cocoa 组件 WebView。例如他调用了 JS 函数:

[webView stringByEvaluatingJavaScriptFromString:@"foo"];

我需要以某种方式等到这个函数被执行并开始做另一项工作。如何在 Objective-C 上完成此操作?我需要这样的东西:

[webView waitUntilJavaScriptCodeIsCompleted];

[webView stringByEvaluatingJavaScriptFromString:] 同步执行,并将 return 执行传入脚本的结果的 NSString。因此,如果您只想知道脚本已执行,请调用该函数,当它 return 时,它已执行。

但是,如果您谈论的是具有某种异步执行的脚本,例如 XMLHTTPRequestsetTimeout,那么您将需要 JavaScript 回调您的 Objective-C 代码,让它知道何时完成。 Here is an example project 就是这样做的。最相关的部分在 AppDelegate 中:

#import "AppDelegate.h"
@import WebKit;
@import JavaScriptCore;

@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;
@property (weak) IBOutlet WebView *webView;

@end

@interface AppDelegate (WebDelegate) <WebFrameLoadDelegate>
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    JSGlobalContextRef jsGlobalContext = _webView.mainFrame.globalContext;

    // Add a function named "allDone" to the window object. It can be called from JavaScript like so:

    JSContext* context = [JSContext contextWithJSGlobalContextRef:jsGlobalContext];
    context[@"allDone"] = ^{
        NSLog(@"All Done was called");
    };

    context[@"jsLog"] = ^(NSString* message) {
        NSLog(@"JSLOG: %@", message);
    };


    _webView.frameLoadDelegate = self;

    NSURL* url = [NSURL URLWithString:@"https://example.com"];
    NSURLRequest *req = [[NSURLRequest alloc] initWithURL:url];
    [_webView.mainFrame loadRequest:req];
}

@end


@implementation AppDelegate (WebDelegate)

- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
    NSLog(@"Page loaded, calling JavaScript");

    // Script that logs a message, and then invokes allDone after 2 seconds.
    NSString* script =
        @"jsLog('Script running');"
        @"setTimeout(function() {\n"
            @"jsLog('javascript timer fired, invoking allDone...');\n"
            @"window.allDone();\n"
        @"}, 2000);";

    NSLog(@"Before stringByEvaluatingJavaScriptFromString");
    [_webView stringByEvaluatingJavaScriptFromString:script];
    NSLog(@"After stringByEvaluatingJavaScriptFromString");
}

@end

结果如下:

Page loaded, calling JavaScript
Before stringByEvaluatingJavaScriptFromString
JSLOG: Script running
After stringByEvaluatingJavaScriptFromString
JSLOG: javascript timer fired, invoking allDone...
All Done was called