【问题标题】:Access javascripts functions from source WKWebView (window.opener)从源 WKWebView (window.opener) 访问 javascripts 函数
【发布时间】:2017-10-07 02:41:10
【问题描述】:

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

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

现在,在本机应用程序中,我正在这样做以重用现有的 javascript 并模拟 Web 架构 -

一个。下面是 1st WKWebView 中网页的 js 调用 -

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

b. WKUIDelegate 拦截此调用 (a) 并打开 2nd 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函数

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

【问题讨论】:

    标签: javascript ios objective-c wkwebview window.opener


    【解决方案1】:

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

    很遗憾,我现在无法验证这一点。但据我记得,诀窍也是不要忽略来自webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures: 委托方法的WKWebViewConfiguration 参数,而是创建第二个WKWebView 实例,将此参数作为initWithFrame:configuration: 参数之一传递。

    此外,根据 Apple 文档,如果您返回正确的 Web 视图实例,您似乎不需要自己加载请求。 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;
    }
    

    【讨论】:

    • 很好,这看起来是一个很有希望的答案。兴奋的。今天试一试。
    • 确认 1. 具有给定配置的新 WKWebView 实例的组合已通过,以及 2. 从列出的方法返回此新实例使得在这些“子页面”和“父页面”的工作,这真是令人难以置信。加载请求也不是必需的。
    【解决方案2】:

    完成任务的更简单方法是拥有一个 WKWebView,并使用 HTML 分隔标题和细节。最简单的解决方案是拥有一个带有标题和所有细节的 HTML 文档,但如果您需要动态添加细节,也可以使用 DOM。使用这种方法,对标题和细节重用 Javascript 将是最简单的。

    【讨论】:

    • 实际上,在 2 个独立的 WKWebViews 中打开数据是一个先决条件,这样我们就可以在我们的应用程序中为该功能重用 Web 应用程序架构。此外,从用户的角度来看,它将在 Web 应用程序和本地应用程序中提供相同的体验。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 2021-03-31
    • 2015-01-11
    • 2014-12-15
    相关资源
    最近更新 更多