The past week I've been spending time working on a client’s HTML5 phone app. The app started crashing for all users that upgraded to iOS 7. In my initial testing, it seemed to be a memory leak. It wasn’t present, however, in iOS 6 or in any of the desktop browsers I tested.
System Dialog Issues
To get around this, I first made a global variable that told me whether or not the user is on an iPhone or iPad with iOS 7. I will be able to use this variable throughout the app anywhere that needs special handling for iOS 7 users.
The quick fix for now is to bypass the confirm dialog for iOS7 users. I'm assuming this is a bug that will be patched in a later update. If not, alternate ways of confirming actions will need to be implemented in the form of a custom modal.
Memory Leak Issue
Then I moved on to diagnosing the memory leak. Doing some Googling I was able to find several mentions of apps crashing or otherwise having issues. Here is a good article with lots of info on different known issues and UI changes that are affecting HTML5 apps.
Unfortunately, I couldn’t find anything that said how to fix my particular issue. I was on my own. Also being a new OS, I hadn’t actively debugged it much yet, so I needed to figure out how to do that better since some things had changed.
First, to use remote debugging mode in Safari, you’ll need to either have OSX Mavericks (which comes with Safari 7) or install Safari 6.1 Beta.
Next, I found that Safari is pretty awful at tracking memory issues. So, I instead used Instruments. For those not familiar, Instruments is a monitoring app that comes with Xcode. I used the "Activity Monitor" template which allowed me to watch the phone from an OS level. Using this app, I was able to track the memory usage of Safari as a whole and see results of changes I made. It also gives you alerts on the timeline, so you can see when the OS does things like closing apps (and why) or putting them into background running mode.
So, using a combination of Safari remote debugging with the Instruments window open allowed me to monitor changes while troubleshooting. I tracked down the memory leak by disabling a screen with lots of buttons and determining it was likely either the DOM elements or event bindings that were causing the leak. This screen was a good indicator because the large number of buttons exaggerated the issue and made it easier to see changes in memory usage.
I was then able to trace the leak to a custom library we're using that is a minimal clone of Knockout.js. The leak wasn't really a bug in the library, but the actions of the library. Adding and removing elements and bindings triggered the bug. I determined through Safari that iOS 7 wasn't properly removing children elements and their listeners when a parent element was removed (an issue previously seen in older versions of Internet Explorer). This was causing every removed element to remain in memory, which therefore caused the memory leak.
My work around was to create a simple recursive function so that whenever an element is removed, it would also find all the children and remove them and their listeners as well. This example is using Zepto.js.
This function is called whenever the library needs to remove an element from the page. Making this change immediately fixed my problem and allowed the app to run stable without any memory leaks.
Now, hopefully these code samples will help you debug cool HTML5 mobile apps that are having issues in Apple's iOS 7.