使用自定义 URL 方案将数据从 UIWebView 发送回 iOS 应用程序中断 Xcode 8/iOS 10

Sending Data from a UIWebView back to an iOS Application with a custom URL Scheme breaks with Xcode 8/iOS 10

在 10 之前的 iOS 版本中,我能够通过在文档上创建 iFrame 或设置将信息从 JavaScript/HTML 加载到 UIWebView 发送回我的应用程序document.location.href 到 Web 视图将尝试加载的自定义 URL:

<html>
<body><input id="clickMe" type="button" value="clickme" onclick="changeWindow();" /></body>
<script type="text/javascript">
    function changeWindow() {
        //create temp frame
        iFrame = this.createIFrame('onStatusChange://eyJ1c2VyTmFtZSI6IkpBTCIsLCJwcm92aWRlciI6IkVtYWlsIn0=');
        //remove the frame now
        iFrame.parentNode.removeChild(iFrame);
    }

    function createIFrame(src) {
      var rootElm = document.documentElement;
      var newFrameElm = document.createElement('IFRAME');
      newFrameElm.setAttribute('src', src);
      rootElm.appendChild(newFrameElm);
      return newFrameElm;
    }
</script>
</html>

然后在客户端上,我将只监听 UIWebViewDelegate 回调 webView:shouldStartLoadWithRequest:navigationType:,并检查 request.URL.scheme 是否等于我的自定义方案(在这种情况下 onStatusChange).

这是 JavaScript 和 iOS 应用程序之间的一种流行通信方式,如 How to invoke Objective C method from Javascript and send back data to Javascript in iOS?.

等常见问题所示

这适用于在 iOS 9 和 10 设备上使用 Xcode 7(Objective-C 或 Swift)构建的任何应用程序。我 运行 遇到一个问题,在使用 Xcode 8 构建的任何应用程序上都没有调用委托方法。就好像网络视图甚至没有尝试加载 URL,这反过来又不会触发委托回调。

是否对 UIWebView 或 WebKit 从 Xcode 7 到 8 或 iOS 9 到 10 进行了任何更改,从而导致其无法正常工作?真正让我感到困惑的是,我在 Xcode 7 中使用 Objective-C 构建的生产应用程序针对 iOS 8 可以在 iOS 10 设备上运行,但是调试构建是使用Xcode 8 个完全相同的代码库不起作用。

那是因为 iOS 现在默认阻止 http 请求。您必须在 info.plist.

中重新启用它

https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33

好吧,长话短说,我们使用特殊的 URL 方案 onStatusChange:// 将 Base64 编码数据从 Web 视图发送回我们的 iOS 应用程序。我相信 UIWebView 在 iOS 上尝试加载以一个或多个等号字符结尾的 URL 并加载 about:blank 而不是实际的 URL 时会出现 10 个阻塞].

由于这在 iOS 9 上完美运行,我假设这是 iOS 10 的缺陷并已打开 rdar://29035522。该雷达的正文中提供了该问题的完整可重现示例。

我正在通读 Base-N encoding RFC 以确定是否可以删除数据字符串末尾的填充 = 字符,或者是否需要从网络中删除这些字符以及在解码数据之前添加到客户端。

我最终实施的解决方案是对 Base64 编码数据进行百分比转义,然后在客户端对其进行取消转义。不是最优雅的解决方案,但可能是最安全的解决方案。