Saturday, June 15, 2013

iOS Port

This last week, I ported my engine and current game to iOS. It was much easier than I expected! I thought it would take me longer, because I didn't realize that iOS actually supports so many of the APIs I used in Linux and Android (such as pthreads and sockets).

Most of the frustrations I experienced were due to these things:

  • Macs do things differently than Windows and Linux, such as text file navigation, using command instead of control, and the Finder having no shortcut to my home folder.
  • I had never used Xcode before.
  • Objective-C is an abomination.
I have no particular love for Windows, but I used it for many years, so I do appreciate that Linux does things like Windows when it comes to hotkeys and the home/end keys, now that I've switched. I also acknowledge that Mac and Objective-C aren't "wrong", just different. Objective-C has some nice features, but I do think the syntax is unfortunate.

Now that I've done Android and iOS development, here's what I think....

Things iOS does better
  • C++ support. The compiler seamlessly compiles Objective-C++ and C++ together, making it trivially easy to integrate my code with the OS. Google has significantly improved C++ support in the last couple years, but I've still had to use JNI for some things, and that is terrible--much worse than Objective-C.
  • Apple has an IDE that integrates seamlessly with the device for native development. I haven't had success getting Eclipse to work with the Android NDK, but I've seen some people have success with it. But Xcode took no effort at all. It detected the device when I plugged it in, and after I provisioned the device, everything worked great.
  • Consistency across devices. I don't have to worry about some obscure device that I haven't tested on.
  • Much simpler application life-cycle.
  • Simpler display device management.
Things Android does better
  • The platform is more open, and so there are fewer hoops to jump through to use a device for development. No account to sign up for, no provisioning portal to monkey with, no cost to start running my code on device.
  • More options for development tools. By far the worst part of iOS development, IMO, is that I have to use a Mac. I have a really nice PC running Linux, but my Mac is a Mac-Mini. To have a Mac as nice as my PC would cost twice what I paid for the PC. Maybe someday I could justify the cost, but right now, I'm glad I can do most of my work on Linux.

Even though the iOS list is longer, the Android list "weighs more". Mostly it's because I prefer Linux over Mac, and my Linux development environment is much nicer. I'm not trying to persuade anyone either way. Overall, I'm quite pleased with how easy it was to port my C++ code over to iOS, because Android and iOS have much more in common than not.

Some problems I encountered...
  • I would recommend staying away from the iOS simulator. If it's all you got, then I guess it's better than nothing. But I kept running into issues where my code worked fine in the simulator, but not on device. So I finally quit using the simulator. Iteration on device with Xcode is just as fast (at least for my project), so I'm not being slowed down at all.
  • In my engine, I override new and delete. My operator delete was being called before anything was loaded, even before static object constructors. When I attempted to free the pointer passed in to operator delete, the app would crash, saying the pointer was never allocated. I implemented a work-around that is working fine. In my operator new functions, I allocate some extra memory and put a sentinel value in front of the pointer I return from operator new. Then in operator delete, I check the 4 bytes in front of the pointer I received to see if it equals the sentinel value. If it does, I free the pointer, otherwise, I just ignore the call completely.
  • Mac has a case-insensitive (but preserving) file system, like Windows. I did not know that, and that lead to some unexpected issues where I had header files named things like "String.h" and "Time.h". I had a namespace to protect the names of my classes, but I ended up having to rename the files.