Как проверить, что данное время WebView выполняет JS-код?
Это какао-компонент WebView. Например, он назвал JS-функцию:
[webView stringByEvaluatingJavaScriptFromString:@"foo"];
Мне нужно как-то подождать, пока эта функция будет выполнена, и начать делать другую работу. Как это можно сделать на Objective-C? Мне нужно что-то вроде:
[webView waitUntilJavaScriptCodeIsCompleted];
1 ответ
[webView stringByEvaluatingJavaScriptFromString:]
выполняется синхронно и возвращает строку NSString результата выполнения переданного сценария. Итак, если вы просто хотите узнать, что скрипт выполнен, вызовите функцию, а когда он вернется, он запустится.
Однако, если вы говорите о скрипте с асинхронным выполнением, например XMLHTTPRequest
или же setTimeout
тогда вам потребуется обратный вызов JavaScript в коде Objective-C, чтобы он знал, когда он закончится. Вот пример проекта, который делает именно это. Наиболее важные части находятся в 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