I am an software developer, and one of the things I develop is apps for mobile - mainly iOS and Android. I would say I’ve been an Android developer for over 6 years and only in recent years have I migrated to being a cross-platform mobile developer using React Native for about just over 3 years now.
One of the things I’ve had to use is Xcode, and when I first started using Xcode (over 3 years ago, I dabbled in an iOS project for about a few hours) the process was absolutely horrendous. I have to admit, however, Apple have been making developing in Xcode a lot more friendlier in recent years. The automatic code signing & certificate generation has been significantly revamped (those who worked on earlier versions of Xcode back in about ’14 will know the absolute horror that was the painful manual process of getting your app certificates, keys, and provisions) as well as general IDE user experience.
The latest update at time of writing improves the iOS Simulator to add buttons to control the simulator directly (take screenshots, rotate device, and tell the simulator to go to the home screen). This is a godsend as the past versions has been like playing Dance Dance Revolution with my fingertips on the keyboard to summon the simulator to do what I wanted to do. This is especially true for the Home Screen navigation command - I highly suspect iOS has some key filter where it debounces home screen button presses. This is fine except for the fact that nothing tells me this is happening so I’m just mashing keys repeatedly like a frustrated lab chimp trying to do a task to get some food reward.
Now that this has been rectified, I want to bring attention to a few things that I feel the simulator is missing not just as someone who has used Android emulators for over half a decade, but mainly as someone who mostly develops app that are highly rich clients that connect to a remote server and the frustrations that come with that with iOS development.
Developing on Android has spoiled me in this regard - with the emulator that comes with Android Studio, you get access to the user filesystem, so you can easily navigate and upload/download files to the device’s emulator. This is perfect for uploading pictures or documents to the phone so you can see how the user interacts with the device. GenyMotion goes one step further and gives you a rooted version of Android so you can see what your application is doing underneath the hood.
This is excellent for debugging things like SharedPreferences values that are being saved - if you have an app that is saving complex objects into SharedPreferences, then you can view how it is being persisted and tweak where necessary (please learn from junior dev me: don’t save complex objects in SharedPreferences. It is terribly inefficient and most importantly it’s like using the handle of a hammer to hammer a nail).
Another great example temporary filesystem issues - if for example if you are saving files temporarily and you want to see if they are saving or not - or in my case - if they were being cleared down successfully. And in my case, they weren’t being cleared down. That would explain why my app slowly grew to GBs of data after many months of running. Oops.
Most importantly for me, it was critical for debugging SQLite database issues. If you have done any SQL work, you know the joys of having your data saved in a convenient, permanent storage. However, you also know some of the frustrations of retrieving that data from the database, especially if you are retrieving data from an online REST endpoint that is changing and storing it locally. There are many issues that may be at play - is it the way I’m storing the data in SQL? (maybe I’ve mistyped the field format or used an incorrect field format?) Or maybe it is the way I’m retrieving it? Perhaps the failure is the REST endpoint isn’t providing the data as necessary, etc.
Being able to just navigate to the SQLite file, “download” it to my desktop filesystem and open it up in SQLite Browser and develop some assertions from the state of the database is powerful and incredible, and goes towards saving lots of time trying to debug the state of the world on the app.
So here’s the thing - you can technically do this with the current iOS Simulator with the extra benefit of having those files right on your machine so you don’t need to faff around with a middleman tool to “download” your database. The problem is that the process is… uh… not exactly straightforward. It’s a complicated process where you have to know (or most likely guess) the UUID of the simulator, and drill down into the data folder and have a poke around until you find the file you want. Having a menu option that would allow us to navigate the simulator’s filesystem would do wonders in helping app developers debug their applications more efficiently.
Better Push Notification Support
This is something of an oddity to me - on Android, the emulators supports receiving remote push notifications (GCM). This is true even with the emulator that is shipped with Android Studio. And generally speaking, push notification support is actually a breeze on Android compared to iOS. With iOS, you will need to have a physical iPhone to receive APNs on your device for reasons that are quite frankly unclear to me. At the very least, I would like to see the iOS simulator support APNs so I don’t need an iPhone.
Having an iPhone is expensive (unless I shell out for the low-end second hand iPhone market, which I do to save on costs) and problematic as I will need to let the iPhone “trust” my Mac, and then there is the issue of ensuring the physical connection doesn’t drop during debugging due to a loose cable, or sometimes with React Native, because my iPhone is on the wrong WiFi network as my Mac. These issues don’t present themselves in a simulator as they are pretty much in the same environment as your Mac (hence the simulator name rather than emulator - a lot of iOS infrastructure is borrowed from Mac it is running on).
While I’m wishing for things that will only happen when pigs fly, I would like to see both Android and iOS tooling have better support for push notifications - perhaps have debugging tools that attach to the device and tell me the device token for the device, which topics the device is actively registered to, and if it can successfully deliver the messages or not and why (e.g. airplane mode, notifications for app disabled).
This is perhaps the biggest bugbear of mine. With Android, the emulators give you a massive variety of cellular options to choose from, from quality of connection, type of connection, if the device is at home or roaming etc, and more. I know GenyMotion offers WiFi speed options, but no cellular connection data restriction. The iOS Simulator is the only mobile device emulation/simulation that does not offer any form of network control. I perhaps wouldn’t be so annoyed if it wasn’t for the fact that there seems to be little control of the network on the physical iPhones too.
I suspect a lot of it is because it is simulating the iOS device, and to do that, it is piggy backing off the Mac’s connectivity. In today’s network connected world, however, it just does not make sense. It is incredibly hard to test how my app behaves in certain network environments using the built in simulator, and I end up having to recreate them by physically attempting to walk out of range with a physical iPhone. Some would claim that this is the better approach, but unfortunately networking is a brittle, non-deterministic system that in the real world is hard to replicate unless you have all the networking equipment at the right firmware connected in the exact same way.
Clearly a massive majority of people can’t do just that, so a sensible solution is Google’s emulator options; give a wide variety of possible options to the developer, and allow the developer to explore the permutations for their own debugging desires. Lacking that, Genymotion’s various options of bandwidth limiting is also great. I would much prefer network options that are similar to Google’s Chrome’s offerings where you get to set the bandwidth, the network latency, and how consistent or random the bandwidth/latency is (stable is perfect for a standing person, random is perfect for a person in transit in a fast-moving transport).
Android’s secret developer menu is a thing of beauty. With several taps to a boring bit of information tucked away somewhere in Android settings, you get access to a wealth of incredible tools built right into Android, including things like forcing closure of apps when minimised (perfect for simulating low memory situations), colouring UI elements based on how expensive the rendering is (great for optimising the UI for snappier UI performance), taking a bug report, plus so many more options that it is incredible as a developer that this feature is built right into all Android phones and is available on emulated phones.
This is something I wish Apple gave with either iOS or simulated devices. If there was an overarching theme to this blog post, it is let us developers in on the device! Let us explore and understand how our apps work in iOS! I will say that with iOS, a lot of the out-of-the-box UIKit framework is so well optimised that a lot of the optimisation debugging tools that come with Android can be chucked out, since if you use iOS’s default framework you are guaranteed to hit 60fps - something that Android just cannot say.
I’ll even go a step further and say that I don’t use 90% of the tools in the developer menu, but the bug snapshot feature in iOS would be excellent. The bug snapshot already somewhat exists when you connect the device to Xcode, but having something built in where an end user can take a bug snapshot of the app and chose to view it on the device would be incredible.
Or even choosing to submit it via some complicated flow which would involve forcing the end user to view the actual data being submitted like a legal document and even asking for their Touch ID at the end to verify it is them. It would probably involve extra details setup in App Store Connect (i.e. opt in with legal T&Cs) and the data would be only viewable in App Store Connect so Apple maintains full control and they can revoke if they suspect abuse via the bug reporting system.
The above approach would be a massive improvement compared to Google’s approach of dumping a zip and then saying “go ahead and email this zip, but be careful who you email it to, as it contains sensitive information” which as a developer and as a user does not inspire confidence.