javascript - 从源 WKWebView (window.opener) 访问 JavaScript 函数

标签 javascript ios objective-c wkwebview window.opener

在我的 iOS 应用程序中,我有 2 个 WKWebView 控件来模拟 Web 应用程序中 2 个选项卡/窗口的父/子关系,以便我们可以重用所有这些 javascript。问题是这两个 WKWebView 之间没有通用的通信 channel 。

网络架构:
- 第一个/主窗口加载我们的内部 JavaScript 函数,并在第二个/子窗口中打开链接。
- 第二个/子窗口加载第三方网页内容。
- 第三方内容使用 javascript 表单源窗口(使用 window.opener/window.parent API 桥)与我们的系统进行通信。

现在,在 native 应用程序中,这就是我正在做的重用现有 JavaScript 并模拟 Web 架构 -

a.下面是从 1st WKWebView 中的网页调用的 js -

  window.open("http://localhost/child.html", "myWindow", "width=200,height=100");  

b. WKUIDelegate 拦截此调用 (a) 并打开第二个 WKWebView -

- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
    // Here, window.open js calls are handled by loading the request in another/new web view
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    WebViewController *webViewController = [mainStoryboard instantiateViewControllerWithIdentifier:@"WebViewController"];
    webViewController.loadURLString = navigationAction.request.URL.absoluteString;

    // Show controller without interfering the current flow of API call, thus dispatch after a fraction of second
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.navigationController pushViewController:webViewController animated:YES];
    });
    return nil;
}

c.在网络/计算机浏览器中,网络应用程序的子窗口可以使用 window.openerwindow.parent 访问源 js 函数

如何在WKWebView中实现相同的功能?换句话说,第二个 WKWebView 中的 js 函数可以从父/源 WKWebView 调用 js 函数?

最佳答案

您绝对不应该从 webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures: 返回 nil,而是返回 WKWebView 的实例。

不幸的是,我现在无法验证这一点。但据我记得,技巧还在于不要忽略来自 webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures: 委托(delegate)方法的 WKWebViewConfiguration 参数,而是创建第二个 WKWebView 实例,将此参数作为 initWithFrame:configuration: 参数之一传递。

此外,根据 Apple 文档,如果您返回正确的 Web View 实例,则看起来您不需要自己加载请求。 WebKit 应该会为您处理这个问题。

总体而言,您的代码应类似于:

- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
    WKWebView *childWebView = [[WKWebView alloc] initWithFrame:CGFrameZero configuration:configuration];
    WebViewController *webViewController = [[WebViewController alloc] initWithWebView: childWebView];

    // looks like this is no longer required, but I can't check it now :(
    // [childWebView loadRequest:navigationAction.request];

    // Show controller without interfering the current flow of API call, thus dispatch after a fraction of second
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.navigationController pushViewController:webViewController animated:YES];
    });
    return childWebView;
}

关于javascript - 从源 WKWebView (window.opener) 访问 JavaScript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46616156/

相关文章:

ios - 如何在 SpriteKit 中高效地画一条线

javascript - 我如何找出发生未处理的 promise 拒绝的地方?

javascript - 从我的网站查询第三方网站的数据库

javascript - 在 Node.js 中发出请求时提示输入要使用的 URL

javascript - 带有 Node Cron 的异步函数

objective-c - objective-c : fix distance between images in touches moved

ios - 在 GraphQL 中编辑类时的正确工作流程

ios - NSUserDefaults 中的 Web API 客户端单例与 token

ios - 突出显示 UILabel 中的子字符串

objective-c - 从不同的对象设置 NSStatusItem 工具提示