如何验证给定时间 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 时,它已执行。
但是,如果您谈论的是具有某种异步执行的脚本,例如 XMLHTTPRequest
或 setTimeout
,那么您将需要 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
这是一个 Cocoa 组件 WebView。例如他调用了 JS 函数:
[webView stringByEvaluatingJavaScriptFromString:@"foo"];
我需要以某种方式等到这个函数被执行并开始做另一项工作。如何在 Objective-C 上完成此操作?我需要这样的东西:
[webView waitUntilJavaScriptCodeIsCompleted];
[webView stringByEvaluatingJavaScriptFromString:]
同步执行,并将 return 执行传入脚本的结果的 NSString。因此,如果您只想知道脚本已执行,请调用该函数,当它 return 时,它已执行。
但是,如果您谈论的是具有某种异步执行的脚本,例如 XMLHTTPRequest
或 setTimeout
,那么您将需要 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