从源 WKWebView 访问 javascripts 函数 (window.opener)
Access javascripts functions from source WKWebView (window.opener)
在我的 iOS 应用程序中,我有 2 个 WKWebView
控件来模拟网络应用程序中 2 tab/window 的 parent/child 关系,以便我们可以重用所有这些 javascript秒。问题是这 2 WKWebView
之间没有通用的通信渠道。
网络架构:
- first/master window 加载我们的内部 javascript 函数,链接在 second/child window.
中打开
- second/child window 加载第三方网站内容。
- 第三方内容使用 javascript 形式源 window 与我们的系统通信(使用 window.opener / window.parent API 桥)。
现在,在 本机应用程序 中,这就是我正在做的,以重用现有的 javascripts 并模拟网络架构 -
一个。 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。在 web/computer 浏览器中,Web 应用程序的子 window 能够使用 window.opener
和 window.parent
访问源 js 函数
如何在 WKWebView
中实现相同的功能?换句话说,第二个 WKWebView
中的 js 函数可以从 parent/source WKWebView
?
中调用 js 函数
完成任务的一种更简单的方法是拥有一个 WKWebView,并使用 HTML 分隔 header 和细节。最简单的解决方案是拥有一个 HTML 文档,其中包含 header 和所有详细信息,但如果您需要动态添加详细信息,也可以使用 DOM 来完成。使用这种方法最容易为 header 和细节重用 Javascript。
你绝对不应该 return nil
来自 webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:
,而是你的 WKWebView
.
的一个实例
很遗憾,我现在无法验证这一点。但据我所知,诀窍是不要忽略 webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:
委托方法中的 WKWebViewConfiguration
参数,而是创建第二个 WKWebView
实例,将此参数作为 [=17] 之一传递=] 参数.
此外,根据 Apple 文档,如果您return正在使用正确的 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;
}
在我的 iOS 应用程序中,我有 2 个 WKWebView
控件来模拟网络应用程序中 2 tab/window 的 parent/child 关系,以便我们可以重用所有这些 javascript秒。问题是这 2 WKWebView
之间没有通用的通信渠道。
网络架构:
- first/master window 加载我们的内部 javascript 函数,链接在 second/child window.
中打开
- second/child window 加载第三方网站内容。
- 第三方内容使用 javascript 形式源 window 与我们的系统通信(使用 window.opener / window.parent API 桥)。
现在,在 本机应用程序 中,这就是我正在做的,以重用现有的 javascripts 并模拟网络架构 -
一个。 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。在 web/computer 浏览器中,Web 应用程序的子 window 能够使用 window.opener
和 window.parent
如何在 WKWebView
中实现相同的功能?换句话说,第二个 WKWebView
中的 js 函数可以从 parent/source WKWebView
?
完成任务的一种更简单的方法是拥有一个 WKWebView,并使用 HTML 分隔 header 和细节。最简单的解决方案是拥有一个 HTML 文档,其中包含 header 和所有详细信息,但如果您需要动态添加详细信息,也可以使用 DOM 来完成。使用这种方法最容易为 header 和细节重用 Javascript。
你绝对不应该 return nil
来自 webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:
,而是你的 WKWebView
.
很遗憾,我现在无法验证这一点。但据我所知,诀窍是不要忽略 webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:
委托方法中的 WKWebViewConfiguration
参数,而是创建第二个 WKWebView
实例,将此参数作为 [=17] 之一传递=] 参数.
此外,根据 Apple 文档,如果您return正在使用正确的 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;
}