从源 WKWebView (window.opener) 访问 javascripts 函数
Posted
技术标签:
【中文标题】从源 WKWebView (window.opener) 访问 javascripts 函数【英文标题】:Access javascripts functions from source WKWebView (window.opener) 【发布时间】:2017-10-07 02:41:10 【问题描述】:在我的 ios 应用程序中,我有 2 个WKWebView
控件来模拟我们的网络应用程序中 2 个选项卡/窗口的父/子关系,以便我们可以重用所有这些 javascript。问题是这 2 个WKWebView
s 之间没有通用的通信通道。
网页架构: - 第一个/主窗口加载我们的内部 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.opener
和window.parent
访问源js函数
如何在WKWebView
s 中实现同样的功能?换句话说,第二个WKWebView
中的js函数可以从父/源WKWebView
调用js函数?
【问题讨论】:
【参考方案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 应用程序和本地应用程序中提供相同的体验。以上是关于从源 WKWebView (window.opener) 访问 javascripts 函数的主要内容,如果未能解决你的问题,请参考以下文章
从源 WKWebView (window.opener) 访问 javascripts 函数
被`webView.uiDelegate`打开后如何处理`window.close`?
jquery 打开页面window.location和window.open的区别