WkWebKit - 加载页面上的 javascript 发现 window.webkit 未定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32771215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:11:30  来源:igfitidea点击:

WkWebKit - javascript on loaded page finds window.webkit is undefined

javascriptioswebkitxcode7wkwebview

提问by Brian B

I'm experimenting with WkWebKit talking back and forth between app and page. I can get javaScript to execute fine using WkWebView evaluateJavascript method, but when I try to execute window.webkit.messageHandlers.myHandler.postMessage('hello world!') on the JavaScript page, I find that window.webkit is not defined.

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

Odd... I'm running in a simulator of iPad with ios 8.4. I thought this was available in original version 8, no?

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

I can't find anyone else posting about this, so perhaps I've done something wrong?

我找不到其他人发布有关此内容的信息,所以也许我做错了什么?

I've even attached my Safari Developer to the simulator's browser, and in the console I try to see what window.webkit is, and sure enough, it does not exist.

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

Note that I add an initial script to run when the page loads (I see this in the javascript editor - the message is logged). And I add a script message handler as well...

请注意,我添加了一个初始脚本以在页面加载时运行(我在 javascript 编辑器中看到了这一点 - 消息已记录)。我还添加了一个脚本消息处理程序......

[EDIT: Adding more code details here]Here is my code:

[编辑:在此处添加更多代码详细信息]这是我的代码:

- (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];
}

//...

采纳答案by soflare

The window.webkit namespace only appears in webview with script message handlers. Make sure that you have called addScriptMessageHandlermethod of WKUserContentController.

window.webkit 命名空间仅出现在带有脚本消息处理程序的 webview 中。确保您已经调用了WKUserContentController 的 addScriptMessageHandler方法。

回答by Pascal Kaufmann

I solved it and problem was that if you set userContentControllerto a new object, that userContentController's WKScriptMessageHandlers will not be registered correctly in Apple's internal code:

我解决它,问题是,如果你设定userContentController一个新的目标,那userContentControllerWKScriptMessageHandler旨意不能在苹果的内部代码正确注册:

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

fixed by using the already instantiated userContentControllerby Apple:

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

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

回答by David Anderson

I ran into this SO because I was experiencing the same issue and this is how I solved it using a custom CustomContentController(subclass of WKUserContentController) instance.

我遇到了这个问题,因为我遇到了同样的问题,这就是我使用自定义CustomContentController( 的子类WKUserContentController)实例解决它的方法。

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

In my case the CustomContentControlleris a subclass of WKUserContentControllerin which the add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)method is called, but I don't believe that is significant.

在我的情况下,CustomContentController是调用WKUserContentControlleradd(_ scriptMessageHandler: WKScriptMessageHandler, name: String)方法的子类,但我认为这并不重要。

I believe that the WKUserContentControllermust be instantiated and applied to a WKWebViewConfigurationbeforethe WKWebView is initialized via WKWebView(frame: .zero, configuration: webViewConfiguration)

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

If the WKWebView has been created and thenyou try change the WKWebViewConfigurationyou will encounter window.webkitnot being available in the JSContext.

如果 WKWebView 已创建,然后您尝试更改WKWebViewConfiguration您将遇到window.webkit在 JSContext 中不可用。

回答by shaojunx

I met the same problem. And after wasting 2 hours, I found this below to work fine. But I don't know why.

我遇到了同样的问题。在浪费了 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);
}