【问题标题】:UIWebView Javascript Window to Window CommunicationUIWebView Javascript 窗口到窗口通信
【发布时间】:2012-12-18 22:32:35
【问题描述】:

我正在开发一个 iOS 应用程序,我正在尝试使用 UIWebView 来显示各种网站。最近我完成了将 Javascript 注入UIWebView 以捕获window.openwindow.closewindow.opener.focus 的实例的逻辑。简而言之,为此,我注入了覆盖上述 JS 函数的 JS,其中包括使用我可以在应用程序的 webView:shouldStartLoadWithRequest:navigationType 方法中捕获的特定方案创建一个 iframe。现在一切正常,包括 window.open 创建一个新的 UIWebView 而不是在同一个窗口中加载。

不过,现在出现了一个问题,即窗口之间的 JS 通信没有可行的解决方案。如果子窗口尝试调用window.openerwindow.parent,它总是返回一个空值,因此,它无法与原始Web 视图通信。

为了了解哪些 iOS 浏览器能够有效地执行窗口间通信,我发现在我的 iPhone 上的 9 个浏览器中,只有 Safari 能够成功地有效地执行这种通信。这让我相信UIWebView 有一些东西阻止了完整的 JS 窗口到窗口通信。

有没有人成功让 UIWebView 与所有 JS 逻辑完全集成,即窗口到窗口的通信?或者有证据证明 JS 窗口到窗口的通信是不可能的?任何方向或建议表示赞赏。谢谢!

【问题讨论】:

  • 同样的问题。运气好吗?
  • 不幸的是,还没有运气。我所能做的就是简单的 JS 注入来覆盖窗口方法(上面提到过)。就我而言,核心问题源于加载到 UIWebview 的网站中的 Facebook 身份验证,用户在身份验证后会卡住,因为没有窗口到窗口的通信。最后,我不得不更改加载到 WebView 中的网站中的逻辑(我碰巧有能力控制),使用直接重定向到 FB,而不是使用带有弹出窗口的正常身份验证流程。

标签: javascript iphone ios xcode


【解决方案1】:

找到可能的解决方案。

将 JavaScriptCore.framework 添加到链接框架和您的 webViewDidFinishLoad:

JSContext *parentCtx = [self.parentWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
JSContext *childCtx = [self.childWebView  valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
childCtx[@"window"][@"opener"] = parentCtx[@"window"];

现在当你从 childWebView 调用 window.opener.test() 时,它会在 parentWebView 中触发测试函数!

我不确定私有 API。 仅适用于 iOS 7

【讨论】:

  • 为什么你说它只适用于 IOS 7?我正在尝试在 IOS 9 中实现这一目标!有什么想法吗?
  • 当时 iOS 7 是最新的 :)
【解决方案2】:

斯威夫特版本

    import JavaScriptCore

    let jsContextA = webA.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext")
    let jsContextB = webB.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext")        

    //Original objc code : jsContextB[@"window"][@"opener"] = jsContextA[@"window"];
    jsContextB!.setObject("opener", forKeyedSubscript: "window")
    jsContextB!.setObject(jsContextA!.objectForKeyedSubscript("window"), forKeyedSubscript: "opener")

【讨论】: