JAL JAL - 1 month ago 28
iOS Question

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.

JAL JAL
Answer

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.