WkWebKit – 在加载页面上的JavaScript发现window.webkit是未定义的

我正在尝试使用WkWebKit在应用程序和页面之间来回交谈。 我可以通过使用WkWebView的evaluateJavascript方法来使javaScript执行正常,但是当我尝试在JavaScript页面上执行window.webkit.messageHandlers.myHandler.postMessage('hello world!')时,我发现window.webkit没有定义。

奇怪…我正在用ios 8.4的iPad模拟器运行。 我以为这是可用的原始版本8,不是?

我找不到任何人发表这个消息,所以也许我做错了什么?

我甚至将我的Safari Developer附加到模拟器的浏览器中,并在控制台中尝试查看window.webkit是什么,并且确实不存在。

请注意,我添加了一个初始脚本,以便在页面加载时运行(我在javascript编辑器中看到这个消息 – 消息被logging下来)。 我添加一个脚本消息处理程序以及…

[编辑:在这里添加更多的代码细节]这是我的代码:

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSLog(@"main view Controller viewDidLoad called..."); // if we are running on an OLD ios (pre v8) WKWebView will not exist. So don't create it if it doesn't exist... if (NSClassFromString(@"WKWebView")) { // WKWebView cannot be dragged onto storyboard, so have to create it manually here. // We have a "ContainerView" called _webContainer that this browser view will live inside // First we create a web view configuration object... WKWebViewConfiguration *wbConfig = [WKWebViewConfiguration alloc]; wbConfig.mediaPlaybackAllowsAirPlay = true; wbConfig.mediaPlaybackRequiresUserAction = false; // inject some Javascript into our page before it even loads... NSString *scriptSource = @"console.log('Hi from the iOS app hosting this page...'); window.hostedByWkWebView=true;"; WKUserScript *userScript = [[WKUserScript alloc] initWithSource:scriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; [wbConfig.userContentController addUserScript:userScript]; [wbConfig.userContentController addScriptMessageHandler:self name:@"myHandler"]; // javascript to use this would be: window.webkit.messageHandlers.myHandler.postMessage // Ok, the config is created, now create the WkWebView instance, passing in this config... _webView = [[WKWebView alloc] initWithFrame: [_webContainer bounds] configuration:wbConfig]; _webView.autoresizesSubviews = true; _webView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; _webView.navigationDelegate = self; // Add the web view to the container view, and tell the container to automatically resize its subviews, height and width. [_webContainer addSubview:_webView]; _webContainer.autoresizesSubviews = true; _webContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; // Set the URL for the webview and navigate there... NSString *fullURL = @"https://myurlgoeshere.com"; NSURL *url = [NSURL URLWithString:fullURL]; NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; [_webView loadRequest:requestObj]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cannot create Web View" message:@"The web view used requires iOS 8 or higher. Sorry." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"", nil]; [alert show]; } //... 

window.webkit命名空间只能在带有脚本消息处理程序的webview中显示。 确保你已经调用了WKUserContentController的addScriptMessageHandler方法。

我解决了它,问题是,如果您将userContentController设置为一个新的对象,那么userContentControllerWKScriptMessageHandler将不会在Apple的内部代码中正确注册:

 WKUserContentController *userContentController = [WKUserContentController new]; userContentController.addScriptMessageHandler(self, name: "jockey") userContentController.addScriptMessageHandler(self, name: "observe") webView.configuration.userContentController = userContentController 

通过Apple使用已经实例化的userContentController来修复:

 webView.configuration.userContentController.addScriptMessageHandler(self, name: "jockey") webView.configuration.userContentController.addScriptMessageHandler(self, name: "observe") 

我遇到了这个,因为我遇到了同样的问题,这就是我如何使用自定义CustomContentControllerWKUserContentController子类)实例解决它。

 let userContentController = CustomContentController() let webViewConfiguration = WKWebViewConfiguration() webViewConfiguration.userContentController = userContentController webView = WKWebView(frame: .zero, configuration: webViewConfiguration) 

在我的情况下, CustomContentControllerWKUserContentController的子类,其中add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)方法被调用,但我不认为这是重要的。

我相信WKUserContentController必须在WKWebView通过WKWebView(frame: .zero, configuration: webViewConfiguration)初始化之前实例化并应用于WKWebView(frame: .zero, configuration: webViewConfiguration)

如果WKWebView已经创build, 然后尝试更改WKWebViewConfiguration ,则会遇到window.webkit在JSContext中不可用。

我遇到了同样的问题。 浪费了2个小时后,我发现下面的工作正常。 但我不知道为什么。

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. WKUserContentController *userCctrl = [[WKUserContentController alloc] init]; [userCctrl addScriptMessageHandler:self name:@"jscall"]; WKWebViewConfiguration *wbConfiger = [[WKWebViewConfiguration alloc] init]; wbConfiger.userContentController = userCctrl; CGSize size = [UIScreen mainScreen].bounds.size; WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 20, size.width, size.height - 20) configuration:wbConfiger]; [self.view addSubview:webView]; webView.UIDelegate = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [webView evaluateJavaScript:@"if (window.webkit === undefined) { alert('未注册的 window.webkit'); } else { window.webkit.messageHandlers.jscall.postMessage({title:'标题'}); }" completionHandler:^(id obj, NSError *error) { NSLog(@"run js completion with error = %@", error); }]; }); } #pragma mark - - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { NSLog(@"run js alert panel message = %@", message); completionHandler(); } #pragma mark - - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { NSLog(@"wkwebview run javascript name = %@, body = %@", message.name, message.body); }