简体   繁体   English

从源 WKWebView (window.opener) 访问 javascripts 函数

[英]Access javascripts functions from source WKWebView (window.opener)

In my iOS app, I have 2 WKWebView controls to simulate parent/child relationship of 2 tab/window in our web app so that we can reuse all those javascripts.在我的 iOS 应用程序中,我有 2 个WKWebView控件来模拟 Web 应用程序中 2 个选项卡/窗口的父/子关系,以便我们可以重用所有这些 javascript。 Problem is that there is no generic communication channel between these 2 WKWebView s.问题是这 2 个WKWebView之间没有通用的通信通道。

Web Architecture :网络架构
- The first/master window loads our internal javascript functions with links opening in second/child window. - 第一个/主窗口加载我们的内部 javascript 函数,并在第二个/子窗口中打开链接。
- The second/child window loads third party web content. - 第二个/子窗口加载第三方网络内容。
- The third party content communicates with our system using javascript form source window (using window.opener / window.parent API bridge). - 第三方内容使用 javascript 表单源窗口(使用 window.opener / window.parent API 桥接器)与我们的系统进行通信。

Now, in the native app , this is what I'm doing to reuse existing javascripts and simulate web archtecture -现在,在本机应用程序中,这就是我正在做的重用现有 javascripts 和模拟网络架构的工作 -

a.一种。 Below js call from the webpage in 1st WKWebView -第 1 个 WKWebView 中从网页调用 js下方-

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

b.The WKUIDelegate intercepts this call (a) and opens 2nd WKWebView - 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. C。 In web/computer browser, the child window of web app is able to access source js functions using window.opener and window.parent在web/计算机浏览器中,web app的子窗口可以使用window.openerwindow.parent访问源js函数

How to achieve the same functionality in WKWebView s?如何在WKWebView实现相同的功能? In other words, js functions in 2nd WKWebView could call js functions from parent/source WKWebView ?换句话说,第二个WKWebView js 函数可以从父/源WKWebView调用 js 函数?

You definitely should not return nil from webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures: , but an instance of your WKWebView .你绝对不应该从webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:返回nil ,而是你的WKWebView一个实例。

Unfortunately, I have no way to verify this right now.不幸的是,我现在无法验证这一点。 But as far as I remember, the trick is also to not ignore WKWebViewConfiguration argument from webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures: delegate method, but create a second WKWebView instance, passing this argument as one of the initWithFrame:configuration: parameters.但据我所知,诀窍还在于不要忽略来自webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:委托方法的WKWebViewConfiguration参数,而是创建第二个WKWebView实例,将此参数作为initWithFrame:configuration:参数之一传递。

Also, according Apple documentation, looks like you don't need to load the request yourself if you're returning correct web view instance.此外,根据 Apple 文档,如果您返回正确的 Web 视图实例,则看起来您不需要自己加载请求。 WebKit should handle this for you. WebKit 应该为您处理这个问题。

Overall your code should look similar to:总体而言,您的代码应类似于:

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

A simpler way to accomplish your task will be to have one WKWebView, and use HTML to separate header and detail.完成任务的一种更简单的方法是拥有一个 WKWebView,并使用 HTML 将标题和详细信息分开。 The simplest solution is to have one HTML document with the header and all of the details, but if you need to add details dynamically that can also be done use the DOM.最简单的解决方案是拥有一个带有标题和所有详细信息的 HTML 文档,但如果您需要动态添加详细信息,也可以使用 DOM。 Reusing Javascript for both the header and detail will be easiest with this approach.使用这种方法,将 Javascript 重用于标题和细节将是最简单的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM