WkWebKit - javascript 在已加载页面上发现 window.webkit 未定义
WkWebKit - javascript on loaded page finds window.webkit is undefined
我正在试验 WkWebKit 在应用程序和页面之间来回对话。我可以使用 WkWebView evaluateJavascript 方法让 javaScript 正常执行,但是当我尝试在 JavaScript 页面上执行 window.webkit.messageHandlers.myHandler.postMessage('hello world!') 时,我发现 window.webkit 未定义。
奇怪...我正在 运行 使用 iPad 的模拟器和 ios 8.4。我以为这在原始版本 8 中可用,不是吗?
我找不到其他人发帖,所以也许我做错了什么?
我什至将我的 Safari Developer 附加到模拟器的浏览器,并在控制台中尝试查看 window.webkit 是什么,果然,它不存在。
请注意,我在页面加载时向 运行 添加了一个初始脚本(我在 javascript 编辑器中看到了这一点 - 消息已记录)。我还添加了一个脚本消息处理程序...
[编辑:在此处添加更多代码详细信息]
这是我的代码:
- (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 命名空间仅出现在带有脚本消息处理程序的 Web 视图中。
确保您已经调用了 WKUserContentController 的 addScriptMessageHandler 方法。
我解决了它,问题是如果您将 userContentController
设置为一个新对象,userContentController
的 WKScriptMessageHandler
将不会在 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")
我 运行 进入这个 SO 因为我遇到了同样的问题,这就是我使用自定义 CustomContentController
(WKUserContentController
的子类)实例解决它的方法。
let userContentController = CustomContentController()
let webViewConfiguration = WKWebViewConfiguration()
webViewConfiguration.userContentController = userContentController
webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
在我的例子中,CustomContentController
是 WKUserContentController
的子类,其中调用了 add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)
方法,但我认为这并不重要。
我认为 WKUserContentController
必须实例化并应用于 WKWebViewConfiguration
,然后 WKWebView 通过 WKWebView(frame: .zero, configuration: webViewConfiguration)
[=21 初始化=]
如果 WKWebView 已经创建,然后你尝试改变 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);
}
最后对我来说,解决方案可以在
的网络视图上启用 javascript
webview?.configuration.preferences.javaScriptEnabled = true
根据苹果的文档:
https://developer.apple.com/documentation/webkit/wkusercontentcontroller
您需要创建您的 userContentController,并添加脚本消息处理程序
userContentController = WKUserContentController()
userContentController.addScriptMessageHandler(foo, name: "foo")
在创建网络视图之前
let configuration = WKWebViewConfiguration()
configuration.userContentController = userContentController
let webview = WKWebView(frame: .zero, configuration: configuration)
在 AFTER 之后执行此操作会导致如下错误:
undefined is not an object (evaluating 'window.webkit.messageHandlers.foo.postMessage')
我正在试验 WkWebKit 在应用程序和页面之间来回对话。我可以使用 WkWebView evaluateJavascript 方法让 javaScript 正常执行,但是当我尝试在 JavaScript 页面上执行 window.webkit.messageHandlers.myHandler.postMessage('hello world!') 时,我发现 window.webkit 未定义。
奇怪...我正在 运行 使用 iPad 的模拟器和 ios 8.4。我以为这在原始版本 8 中可用,不是吗?
我找不到其他人发帖,所以也许我做错了什么?
我什至将我的 Safari Developer 附加到模拟器的浏览器,并在控制台中尝试查看 window.webkit 是什么,果然,它不存在。
请注意,我在页面加载时向 运行 添加了一个初始脚本(我在 javascript 编辑器中看到了这一点 - 消息已记录)。我还添加了一个脚本消息处理程序...
[编辑:在此处添加更多代码详细信息] 这是我的代码:
- (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 命名空间仅出现在带有脚本消息处理程序的 Web 视图中。 确保您已经调用了 WKUserContentController 的 addScriptMessageHandler 方法。
我解决了它,问题是如果您将 userContentController
设置为一个新对象,userContentController
的 WKScriptMessageHandler
将不会在 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")
我 运行 进入这个 SO 因为我遇到了同样的问题,这就是我使用自定义 CustomContentController
(WKUserContentController
的子类)实例解决它的方法。
let userContentController = CustomContentController()
let webViewConfiguration = WKWebViewConfiguration()
webViewConfiguration.userContentController = userContentController
webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
在我的例子中,CustomContentController
是 WKUserContentController
的子类,其中调用了 add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)
方法,但我认为这并不重要。
我认为 WKUserContentController
必须实例化并应用于 WKWebViewConfiguration
,然后 WKWebView 通过 WKWebView(frame: .zero, configuration: webViewConfiguration)
[=21 初始化=]
如果 WKWebView 已经创建,然后你尝试改变 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);
}
最后对我来说,解决方案可以在
的网络视图上启用 javascriptwebview?.configuration.preferences.javaScriptEnabled = true
根据苹果的文档:
https://developer.apple.com/documentation/webkit/wkusercontentcontroller
您需要创建您的 userContentController,并添加脚本消息处理程序
userContentController = WKUserContentController()
userContentController.addScriptMessageHandler(foo, name: "foo")
在创建网络视图之前
let configuration = WKWebViewConfiguration()
configuration.userContentController = userContentController
let webview = WKWebView(frame: .zero, configuration: configuration)
在 AFTER 之后执行此操作会导致如下错误:
undefined is not an object (evaluating 'window.webkit.messageHandlers.foo.postMessage')