简体   繁体   中英

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

On iOS versions previous to 10, I was able to send information from the JavaScript/HTML loaded into a UIWebView back to my application by creating an iFrame on the document or setting document.location.href to a custom URL which the web view would tried to load:

<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>

Then on the client, I would just listen for the UIWebViewDelegate callback webView:shouldStartLoadWithRequest:navigationType: , and check to see if the request.URL.scheme was equal to my custom scheme (in this case onStatusChange ).

This is a popular way of communicating between the JavaScript and an iOS app, as seen in popular questions such as How to invoke Objective C method from Javascript and send back data to Javascript in iOS? .

This works on any app built with Xcode 7 (Objective-C or Swift) on iOS 9 and 10 devices. I'm running into an issue where the delegate method is not called on any applications built with Xcode 8. It's as if the web view isn't even trying to load the URL, which in turn is not triggering the delegate callback.

Were there any changes to UIWebView or WebKit from Xcode 7 to 8 or iOS 9 to 10 which would cause this not to work? What's really puzzling to me is that a production app I have built with Objective-C in Xcode 7 targeting iOS 8 works on an iOS 10 device, but a debug build built with Xcode 8 of the exact same codebase does not work.

Ok, long story short we use a special URL scheme onStatusChange:// to send Base64 encoded data from the web view back to our iOS application. I believe UIWebView on iOS 10 chokes when trying to load a URL that ends in one or more equals sign characters, and loads about:blank instead of the actual URL.

Since this works perfectly on iOS 9, I'm assuming this is a defect with iOS 10 and have opened rdar://29035522 . A full reproducible example of the issue is available in the body of that radar.

I am reading through the Base-N encoding RFC to determine if it is acceptable to remove the padding = characters at the end of my data string, or if they need to be removed from the web and added on the client before decoding the data.

The solution I ended up implementing was percent-escaping the Base64 encoded data, and unescaping it on the client. Not the most elegant solution, but probably the best for safety.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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