Friday, June 7, 2013

Day 40: Retrospective

Now that I am once again focusing primarily on Android development this may be the end of the road for my crash course in iOS (at least for now). Here is a summary of some of the lessons learned during my brief experiment as an iOS user and developer.

1. Android and iOS are more alike than different.


Despite different hardware, operating system, language, and development environment ultimately both Android and iOS are mobile computing platforms. You still need to solve many of the same problems including resource management, network communication, and designing for a small screen.

Some aspects of iOS development have actually helped me become a better Android developer. Using the common delegate pattern on iOS has helped reinforce the value of extracting logic from my Android Activities and Fragments into objects with a proper Interface (Protocol).

Even the differences in syntax between Objective-C and Java, while significant at first, quickly fade into the background as you get used to all those square brackets.

2. The differences are significant.


Building a UI is very different on iOS. The technique most Android developers use is based on editing layouts in XML. In iOS UI editing is done graphically through Interface Builder or Storyboards. Or written purely in code. But there is really no good option for a declarative markup syntax since the code produced by the graphical tools is not human readable.

Navigation and integration are also drastically different on iOS. Android uses Intents to transition between screens within the same application or even to integrate with other applications on the device. In iOS transitions are a function of the graphical UI editor, or can be accomplished in code by keeping a reference to the various view controllers and manually adding/removing subviews from the root view controller. Integration with other applications is not possible in the same manner as Android but can still be accomplished to some extent using techniques like a custom URL scheme for deep links or a shared Pasteboard.

Storyboards in XCode

3. Everything is in the foreground.


As an iOS user and developer I could not get over the fact that almost everything must happen while the app is in the foreground. The end result is that many apps feel slow and stale as compared to their Android counterpart. Not being able to spin up a background service to periodically sync data or poll location means that each time you open an app you have to wait for it to fetch fresh data.

For example, each time I would receive a notification for new message in GMail on iOS I would start reading a preview of the message in the notification. Then I would open the GMail app and I would have to wait for the data to sync before I could continue reading the rest of the message. I guess I am spoiled on Android but this feels like bad UX. Making users wait to see the newest content is a waste of their time.

4. Test-driven development is alive and well on iOS.


Many times in the past I have heard from iOS developers that unit testing and TDD/BDD is either difficult or impossible. I'm not sure how much this has changed in recent versions of the OS, but in my experience testing on iOS is not only possible but the tools are even better than what is currently available on Android. While projects like Robolectric have improved the situation, Android still has a long way to go to enable efficient unit testing that is fully integrated with the platform.

On iOS you have a variety of testing frameworks available. During this experiment I successfully test-drove my code using OCUnit, Kiwi, and KIF. Other options include Cedar, Cucumber/Calabash, and UI Automation.

And iOS has the added advantage that running tests on the simulator is much faster than deploying to an Android emulator or device which means that even running integration and functional tests though the UI is quite fast comparatively.

For a sample test-driven iOS app check out Three the Hard Way (HelloTDDiOS).

Summary


Even though hands-on iOS development may not be something I am going to do professionally on a regular basis, increasing my literacy of Objective-C and my understanding of the platform has still been beneficial.

It has improved my vocabulary and comprehension in discussions with iOS developers. It has given me a better overall understanding of mobile ecosystems that span across multiple platforms. And it has prompted me to make an effort to work more closely with my iOS counterparts day-to-day because in the end we are solving many of the same problems.

Only Android does it a little bit betterAndroid wink


Big thanks to Matt Smollinger and Matthew Lim for their reviews and feedback on the draft of this post.

Wednesday, May 15, 2013

Day 21: Google I/O

I am writing this post while waiting for the keynote to begin at Google I/O 2013.

In anticipation of the largest Android event of the year, I've temporarily switched back to my Nexus 4 from the iPhone 5. Originally I considered sticking with the iPhone this week as a true test of my commitment to this experiment but ultimately decided I didn't want to miss out on any Android goodness while here.

What has been surprising here at the Moscone Center is the number of iPhones I see being used by attendees and the number of developers I've spoken with who work on both Android and iOS. Perhaps dual specialization as a mobile developer is not as uncommon as it once was.

Well the keynote is about to begin. In typical conference fashion the wi-fi here is barely functional so I'll have to post this later.

Update:

Posted from my new Chromebook Pixel. Thanks Google!

Wednesday, May 8, 2013

Day 14: TDD

I have been a long-time proponent of the principles and benefits of Test-Driven Development. All of my Android projects use Robolectric and the built-in instrumentation testing framework. So naturally, when I decided to explore iOS, testing was one of the first things I wanted to investigate.

Fortunately there is no shortage of quality testing frameworks for iOS. I decided to focus my efforts on 3 of the available frameworks:

OCUnit

Based on the SenTest framework, OCUnit is a traditional xUnit style unit testing tool that comes bundled with the iOS SDK.

Kiwi

An RSpec style testing tool with an extensible expectation syntax and built-in mocking tools for Behavior-Driven Development (BDD).

KIF

A fully automated functional testing tool that simulates user interactions by leveraging accessibility attributes provided by the OS.


Three the Hard Way (HelloTDDiOS)


Three the Hard Way is a sample application I created to showcase all 3 testing frameworks in action. The app itself is very simple but provides a good forum for experimenting with various testing techniques.

Based on Your first iOS App tutorial on Apple Developer, Three the Hard Way allows you to enter a name via text input, click a button, and view the resulting greeting.

       


Development of the app was 100% test-driven using OCUnit. Below is an example of tests written to exercise the button callback in the view controller.

And the production code that was written to satisfy these tests. Notice how the tests use an instance of MockHelloTDDViewControllerDelegate to test the view controller in isolation rather than GreetingFactory (the actual delegate used in production).

And here are the same tests rewritten using Kiwi.

Finally, here is the end-to-end integration test using KIF that tests the button through a scripted UI interaction.

In order for KIF to locate the UI elements, we must set the accessibility labels in (void)viewDidLoad.

Fork the full project at https://github.com/ecgreb/Three-the-Hard-Way. Feedback is welcome.

Monday, May 6, 2013

Day 12: Battery Life

Standby Battery Life

This weekend I didn't charge my iPhone 5 from the time I left work on Friday afternoon until Sunday night when I went to bed. And I still had 17% battery remaining. That is rather impressive.

Granted I did not use my phone very much as it was beautiful outside and I spent most of the weekend power washing and applying joint sand to my brick patio. This is not a scientific study, but in my experience the standby battery life of my iPhone is much better than what I have had on any Android device (and I've had a lot of them).

Background Sync

Again, we are talking about battery consumption during times of sparse usage here. I can only assume one of the reasons for the iPhone's strong standby battery life comes from the fact that very little is happening when the device is idle. Apple does not allow third party applications to spin up long-lived background services with a few exceptions like Android does.

There is a tradeoff here. When I receive an APN to let me know I have a new message in GMail I can even read a preview of the message in the notification. But then when I open the GMail app to read the rest of the message it's not there. I have to wait for the app to sync with the server. With Android, the new message would already be there. And not just for Google apps-- any app can take advantage of background sync using a Service.

For me the extra standby battery life is not worth the time I have to wait each time I open an app for it to fetch fresh data from the server. In this age of on-demand computing it should already be there.

What do you think?

Thursday, May 2, 2013

Day 8: Provisioning Profiles

Steps required to install and run a development build of an Android app on a local device:
  1. Open Settings > Developer options menu on the device and check the box for USB Debugging.*
  2. Build and launch your app using Eclipse, IntelliJ, Ant, Maven, or Gradle.
  3. There is no step 3.
* On newer devices running Android 4.2 or later, if the Developer options menu is not visible go to Settings > About phone and tap the build number 7x to enable developer options.



Steps required to install and run a development build of an iOS app on a local device:
  1. Create an Apple ID at https://developer.apple.com/register.
  2. Register for the iOS Developer Program ($99) or join an existing iOS Enterprise Developer Program account (via email invite).
  3. Complete account creation and fill out professional profile.
  4. Sync your device with a computer using iTunes.
  5. Add your device to the Member Center using Xcode Organizer tool.
  6. Create a Certificate Signing Request (CSR) using Keychain Access utility.

             

  7. Upload the CSR to the Member Center and generate a signed certificate (requires admin access).
  8. Download the signed iPhone Developer certificate and install it in Keychain Access.
  9. In the Member Center, check the active iOS Provisioning Profiles for development. If there is an active development profile managed by XCode, you should be able to refresh the Provisioning Profiles in Xcode Organizer to automatically update to include the new development certificate. If not, or if the existing profile fails to update (as it did for me), proceed to step 10.

             

  10. Create a new iOS Provisioning Profile for Development. Be sure to include the iPhone Developer certificate you just created and your device in the profile.
  11. Download the new Provisioning Profile and drag it into the iTunes Library panel.

            

  12. Sync your device with iTunes to install the new Provisioning Profile.
  13. Build and launch your app using Xcode or (in my case) AppCode.
Just a bit more complex that what I have been used to with Android. My actual process involved many more steps of trial and error before I was able to distill it down to this (streamlined?) version.

If you are new to iOS like me... hopefully this guide will save you some time and frustration.

If you are a seasoned iOS developer... isn't there a better way!?

Monday, April 29, 2013

Day 6: Top 20 Thing I Miss Most about Android

Top 20 things I miss most about Android after my first week as an iOS user:
  1. Show password
  2. Background sync
  3. Lower case letters keyboard when keyboard is lower case
  4. Easy access to frequently used punctuation on keyboard
  5. Long press for numbers and symbols on keyboard
  6. Tap to place cursor in the middle of a word
  7. Home screen widgets
  8. Lock screen widgets
  9. Unlock pattern
  10. The Action Bar
  11. Developer options
  12. Stay awake while charging
  13. Logcat
  14. FREE client for 1Password
  15. Photos in my contact list and favorites
  16. Ringtones and alarms (Who really uses Bark or Duck?)
  17. Share button
  18. One click app install
  19. Google Now
  20. Back button
Update: Google Now launched today for iPhone and iPad. I'm not sure if/how it will be able to achieve the same level of prediction and integration with other apps as on Android - but we shall see.

http://googleblog.blogspot.com/2013/04/google-now-on-your-iphone-and-ipad-with.html

Friday, April 26, 2013

Day 3: Development Environment

XCode is the official IDE and a natural choice for new iOS developers. However I have been a longtime user of IntelliJ IDEA for Android development as well as other JetBrains products including PhpStorm, PyCharm, and RubyMine.

Hoping to leverage my existing knowledge of these other IDEs, after a brief introduction to XCode I decided to try AppCode, the JetBrains Objective-C IDE.

AppCode runs on top of XCode, meaning XCode must be installed, and even uses XCode for all graphical UI editing capabilities. Anytime you open a Storyboard (.storyboard) or Interface Builder (.xib) file in AppCode, it launches XCode to interact with that file.

At first glance I like the overall layout of AppCode better, but that could be just because I am unfamiliar with XCode, where I still have a hard time finding things. And AppCode's Darkula theme is so much easier on the eyes than the bright white editor of XCode. Already being fluent with IntelliJ's keyboard shortcuts, it was pretty easy to get started. AppCode also gives you the option to use XCode's keyboard shortcuts (as well as many others).

One of the features I appreciate most about IntelliJ is the powerful code completion and code generation engine. The ability to quickly hit Option+Enter to generate a new class/method/variable on the fly saves a ton of time when coding. While the same concept exists in AppCode, these tools seem slightly less refined in IntelliJ's younger cousin.

For example, when attempting to call a method that does not exist, the statement is underlined in red.

The method someFunctionThatDoesNotExist appears with a red underline because it is not yet defined.
Pressing the keyboard shortcut for QuickFix Option+Enter reveals the ability to create a new method or property. This will update the header file StackOverflowManager.h and implementation file StackOverflowManager.m with a skeleton for the new method. If this function included input parameters those would also be configured through a form in a modal window.

The Option+Enter keyboard shortcut for Quick Fix reveals the ability to create a new method or property.
Here is another example of calling an undefined method, but this time the call is nested inside a macro. This example shows a SenTest macro from the OCUnit testing framework.

The method someFunctionThatDoesNotExist is currently undefined.
Unfortunately when the undefined method is written as an argument to the macro the option to create a new method or property is not available. This is unfortunate because calling a new function inside a macro is especially common when writing new code using test-driven development.

Quick fix keyboard shortcut does not reveal create method/property options when nested in a macro.
The workaround here is to declare a local variable to capture the result of the undefined method.

Result of someFunctionThatDoesNotExist is assigned to a local variable.
Now declared outside the macro the advanced code generation tools are once again available.

Option to create new method/property is revealed when declared outside the macro.
What also seems to be missing is the ability to quickly generate a new test method using Control+N in a test file. Looks like I will be adding a custom Live Template for this use case, which is an AppCode extension to XCode snippets.

For more code generation goodness, checkout this article on the official AppCode Blog.

Does anyone else have experience using both XCode and AppCode? If so, I am interested to hear about which one you like better and why in the comments.

Thursday, April 25, 2013

Day 2: Google Sync

All of my contacts, events, and personal email reside in Google land. Syncing Google data with Android is for the most part a seamless experience. Setting up sync with my new iPhone required some config but really wasn't bad (once I found the correct set of instructions).

Doing a quick search for "sync google with iphone" turns up the following results.


The first hit looked promising so I clicked it and dove right in. The page described syncing Google contacts, calendar, and email with iOS using Microsoft Exchange ActiveSync protocol. This seemed weird to me but I went ahead and gave it a try.


No dice. After several more attempts I was stuck. Eventually I noticed the big yellow warning banner at the top of the page! In short-- these are not the instructions you are looking for.


Apparently Google dropped ActiveSync support for all accounts except Google Apps accounts effective January 30, 2013. (This is probably old news to regular iOS users.) The banner even conveniently provides a link to the proper set of instructions for personal accounts.

According to the new instructions:

  • Contacts should be synced to the iOS Contacts app using the CardDAV format.
  • Calendar should be synced to the iOS Calendar app using the CalDAV format.
  • GMail app should be used to instantly receive and send mail.*

* This last point is important. Since dropping support for ActiveSync, it is no longer possible to receive GMail via push to the iOS Mail app. It is still possible to sync GMail using IMAP, but updates will be based on a polling interval rather than push.

Using the official GMail app also offers several other advantages including multiple account support, real-time notifications, and improved search.

The updated instructions were easy to follow and now I am happily using all of my Google services on the iPhone 5.


4G Update

Yesterday while driving into the city I was able to pick up a 4G signal on the iPhone for the first time. So it's not that 4G is entirely broken. But the question remains why would I get T-Mobile 4G on my Nexus 4 but not on the iPhone 5 at home and at work with the same plan?

Tuesday, April 23, 2013

Day 1: Activation

Today my iPhone 5 (unlocked GSM) ordered directly from Apple was delivered and I promptly popped out the T-Mobile SIM card from my Nexus 4 to make the swap. Unfortunately at this point I realized my Micro SIM would be of no use since the iPhone 5 requires a Nano SIM.

I have cut down many standard size (Mini) SIM cards before to fit into Micro SIM slots when switching devices. But due to the extremely thin margin for error on the Nano SIM and actual differences in the contact points I decided not to attempt the procedure myself this time. So I was off to the T-Mobile store.



Activation turned out to be a bit more of a process that I had expected. Not only did I have to purchase and activate a new Nano SIM card, but the iPhone required a series of software updates and restarts over the course of 10-15 minutes to properly configure for the T-Mobile carrier network. This is very different from what I was used to with GSM Android devices that are ready almost instantly after popping in a new SIM.

In the end it worked. I made my first phone call and sent my first SMS with the iPhone. The only issue I am having now is that 12 hours later the device is only showing only extended network coverage. This despite having a 4G plan and having successfully connected to 4G on Android devices at the office and at home using my T-Mobile account prior to making the switch.

I'm not sure whether this is just a display issue (am I really getting 4G even though it says "E") or an actual problem with the network. If the issue is real, is it a problem with the device or T-Mobile? Or both?

At the time of writing this I am still working on getting all of my Google services (mail, calendar, contacts, etc.) synced to the iPhone. More on this tomorrow.