Adapting my Ionic framework app for iOS 9: Problems and Solutions

What I do

I develop cross-platform hybrid apps for mobile devices using the Apache Cordova platform, which builds native mobile applications using HTML, CSS and JavaScript. Also I use the Ionic front-end SDK, which is based on a Cordova platform and AngularJS Framework.

iOS 9 Release

September 16 was the official iOS 9 release date. After upgrading our Apple devices to iOS 9 and XCode to version 7 with iOS 9 simulators, we started to experience some problems with apps developed using the Ionic framework. We didn’t really have a choice in the matter: we needed to adapt our apps to function in line with the new specifications and fast.

Getting ready

Of course we knew about the iOS 9 version upgrade well in advance. I’d read the article from Ionic’s official blog about preparing for iOS 9 to get ready. In the article the guys from Ionic explain about possible bugs and solutions to fix them. Despite that, I experienced a number of issues that required a little problem solving of my own.

A strange console error

When I built my project in that new Xcode 7 and ran it on the simulator, my app didn’t start properly, instead I could see only the background of <body>. Then I debugged the app with Safari Developers Tools and got a strange console error from a line of the vendor.js file. In this file I had “glued” Ionic files and third party libraries. The error I got in the console looked like this:

Error: SyntaxError: DOM Exception 12
setRequestHeader@[native code]

Looking for solutions

When I started searching for this error I found this forum thread. It said that the contributors had got this error too and that the error is triggered when a network request is made using the $http service. I used $http in my app too, but I didn’t make any request through it when the app was starting. Also, in the forum thread it said that the problem is triggered by adding custom headers to a network request. To solve the problem, headers shouldn’t have a leading space in the value. I had custom headers but I didn’t have any spaces before the value. So I decided, (wrongly as it turned out), that this article couldn’t help me.

Here’s what I tried next:

  1. I read all the advice from Ionic’s blog article again and tried to apply it to my project – it didn’t help.
  2. I decided that as I was getting the error in vendor files, I should try updating Ionic Framework, Ionic CLI and all third party libraries (Angular, Restangular, ngStorage, …) – it took some time, but when I ran the app again I got the same error.
  3. I created a new “clear” ionic app and it worked properly – so I was sure that the problem was somewhere in my code.
  4. I started debugging the app and digging around in my code in “the old school way” – trying to cut out blocks of code and see if the app would then work (because I got the error before it was possible to use any Safari dev tools for debugging). In this way I found out which line in my code was triggering this error. It was this line:
$http.defaults.headers.common.Authorization = 'Basic ' + $localStorage.user.authToken;

I use my own service in dependency injection which executes a line of code (see above) when the service is initialized. This is why the $http service was also causing the error I was encountering. I removed this line from my code and replaced it with authorization token headers in the configuration of each request, like this:

$http.post(appConfig.apiUrl + 'profile', data, {
 headers: {'Authorization': $localStorage.user.authToken}
})

After that my app started to load (Hurrah) which let me see some other problems (Booo).

Additional problems and how I solved them

The other problems included:

  1. When i made requests for some API URLs, I got this error in the console log:

Failed to load resource: The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.

This problem was quickly fixed as Ionic has some advice to give about this particular case. In this case, special keys need to be added for the .plist file of our xcode project. I added these configuration lines to my config.xml:

...
<platform name="ios">
 <config-file platform="ios" target="*-Info.plist" parent="NSAppTransportSecurity">
 <dict>
 <key>NSAllowsArbitraryLoads</key><true/>
 </dict>
 </config-file>
</platform>
…

and added this to the after_prepare hook from the Ionic Generator. Problem fixed.

2) I got errors in my code because some plugins (file, file-transfer, inappbrowser) have been updated and now have a different API. This just required rewriting part of my code so that it used the API correctly.

3) Also Ionic warned about a potential breaking change introduced into UIWebView which can affect apps that rely on window.location semantics. To avoid these issues I implemented their suggested patch: ngIOS9UIWebViewPatch

In the end, I was able to get my app working properly. Good luck with your own hybrid apps!