Showing posts with label ios. Show all posts
Showing posts with label ios. Show all posts

Monday, June 24, 2013

The Importance of Being Whimsical

What makes a good app? Sure, it should do what it claims to do, intuitively and efficiently. But that is just the base line. How do you stand out from the sea of apps? You need to go above and beyond, and whimsy may just be the secret ingredient you need.

Tumblr

At the keynote at AnDevCon Boston, Chris Haseman and Zack Sultan showed us how they designed and implemented the Tumblr app. They shared many tips and tricks to make your app look good and work well, but the recurring theme is to delight your user.

There are many whimsical touches to Tumblr, one being the pull-to-refresh animation:

Tumblr could have gone with a loading text or a standard spinny, but this custom animation brings the app a notch above others. It entices users to refresh more, increasing engagement. This is the power of whimsy.

Welcome animations

Animation is a great way to add whimsy to your app. At AltWWDC, Ben Johnson showcased many different apps with effective animations.

This is the welcome page of the Just Landed app. The subtle movement of the plane and the clouds hints to the users that there is more to come, encouraging them to try it out. You can argue that this is gratuitous, nothing more than eye candy. It adds no functionality to the app. But apps are not just about functionality. You need to connect with your users, make them feel good using your app. A delightful welcome page sets the stage for the rest of the app, and helps them stay engaged.

Reward your users

What’s happening here? You’re in the Zappos app, thought these sneakers look good, and pressed the "add to cart" button. A cat floated out, dropping the shoes into your cart Mary-Poppins style. What’s your reaction? Cool, I want to see that again. How? By adding more stuff to your cart! A whimsical gesture that directly increases the bottom line. I doubt anyone can call that gratuitous.

Whimsy everywhere

So you want to be whimsical. What to do? Whimsy hinges on unexpectedness, so it's a bit of an oxymoron to provide a formula. Fortunately, you have already taken the first step - awareness. Once you start paying attention, you will see whimsy everywhere, adding them to your repertoire, ready to inspire your own.

The other day I found whimsy in the most boring place of all - airplane safety video.

The video caught my eyes with a teeny tiny suitcase that got stowed under the seat. I found myself looking forward to more funny shots, and paying attention throughout. If you graph the whimsical moments, you can see that they frontload them to set the tone:

Once you are hooked, they get down to business and show you some serious content. Just before you get bored, they sprinkle a bit of whimsy again, keeping you on your toes, watching the whole video looking for more.

Unpredictable delights

It was said that we are addicted to emails because they are like slot machines. Most of the time you get nothing, but once in a while you get something awesome, and so you keep playing, in hope of hitting jackpot. Whimsy does the same trick to your app. It delights users in unpredictable ways, keeping them engaged, and separates your app from the herd.

Monday, February 4, 2013

Learning iOS as an Android developer

As a veteran Android developer, I have always been curious about the iOS platform. Is Objective-C hard to learn? Is it really much easier to make beautiful UI in iOS?

I decided that the best way is to write an app on both platforms and compare. An app that I actually launch, so I experience the whole process, from coding to UI design to distribution. The result is Heart Collage, available on both Apple App Store and Google Play.

Here are my thoughts after learning iOS for two months.

The setup

I wrote an universal app in iOS 6, with auto layout and storyboard. I chose iOS 6 for the new functionalities like UICollectionView and UIActivityViewController. Auto layout and storyboard trickled down from the iOS 6 decision. Since I was on the latest version, I may as well take advantage of the latest tools.

Learning curve

The first three weeks were painful. Not only I did not know anything, but I lacked the vocabulary to ask questions. I would search for something and find 5 Stack Overflow threads, all of which sounding kind of related to what I need, but not really. It was really frustrating.

But things changed on the third week. By then I knew which classes I was using, so I prefixed all my image manipulation searches with UIImage, navigation searches with UINavigationController. I also had some basic understanding of how things were organized, and was able to skim and judge if a particular thread was relevant.

Once I knew how to find answers on the internet, development speed really picked up. I felt like I was actually coding, instead of walking into a wall.

UI Editing

Initially I thought I would really be bothered by all the square brackets in Objective-C, but I got used to the syntax fairly quickly. What tripped me up was Interface Builder / Storyboard.

In both iOS and Android, there are two ways to specify layout: xml and code. The difference is that Android has readable xml. Not so much in iOS.

Both systems use unique ids to refer to the various components. In Android, you define the id like this:

<Button android:id=”@+id/start_button” />

The build system gathers all the id tags and generate unique ids in Java:

public static final class id {
  public static final int start_button=0x7f08003b;
}

To refer to a view in your code, use findViewById:

Button startButton = (Button) findViewById(R.id.start_button);

In iOS, the storyboard directly generates the unique ids in the xml:

<button id="vMl-QF-OAb" />

To refer to a view in your code, you first define an IBOutlet in your .h file, go to the storyboard, right-click drag your view into the view controller. This assumes you have already told storyboard that this particular window is linked to that view controller, otherwise the IBOutlet will not show up.

It all makes sense after the fact, but when I first started I would drag and drag and drag and not be able to link the views. Sometimes I forgot to specify the view controller. Other times I forgot to add the IBOutlet. On late nights I forgot it’s right-click drag, not just drag.

The most difficult part is that I cannot compare my implementation with sample code because it is all visual. In Android I would diff the whole project, code and xml and all, to find out what I missed. The XML produced by Interface Builder / Storyboard is not diff friendly at all.

Built-in Components

Once I got the ropes around UI editing, I can build the various screens for the app. People claim that the built-in components in iOS are much more beautiful than Android, but the gap has significantly narrowed since Ice Cream Sandwich. Sure, the iOS UIPickerView is still much more delightful to use than the Android Spinner, but the basic components like buttons are pretty much on par.

There was one thing that was much much easier to use on iOS than Android: the camera preview. Heart Collage shows a square camera preview for you to pose. In iOS, I can ask for a preview window in any aspect ratio, and the system crops the camera feed automatically. In Android? The system stretches the camera feed to the aspect ratio of the preview. To make a square camera preview I had to make the preview window the same aspect ratio as the camera feed, and cover up some parts so it appears to be a square. It was really involved. Who wants a distorted camera feed anyway? Cropping is the right thing to do.

For the rest I almost always find direct correspondences: ImageView maps to UIImageView, TextView maps to UILabel, ListView is roughly UITableView, and GridView... well GridView is interesting. Up until iOS 5 there is no built-in grid view. You have to use a UITableView and layout the cell on each row yourself. I was shocked when I heard that. Guess I’m spoiled by Android? We have that since version 1! Fortunately UICollectionView was introduced in iOS 6, and unlike Android, it is okay to target the latest OS release because most users upgrade very quickly.

This brings us to the famous fragmentation debate.

Fragmentation

There are two kinds of fragmentation: OS version and device form factor.

OS version

iOS is definitely better positioned against OS version fragmentation, since Apple is the sole manufacturer of all iOS devices and they completely control the OTA schedule.

Device form factors

Until recently the device form factor was pretty uniform. There is Retina and Non-Retina, that’s it. Different density, same aspect ratio. Same aspect ratio means you can still use a coordinate-based layout system and align your views in Interface Builder.

Everything was peachy until iPhone5. Suddenly there is a different aspect ratio, and Apple needed something more powerful than struts and springs. The solution is Auto Layout.

Auto layout is a declarative way to specify the positions of your views. Instead of saying, put this image 240 pixels from the top, you say, center vertically. The system computes the xy-coordinates based on your constraints, so it adapts well to different form factors.

Auto layout sounds good on paper, but it is really clunky to use in practice. In Interface Builder, you still drag and drop your views, and XCode tries to guess your intention. Most of the time it gets it wrong, so I have to remove the automatically generated constraints and create my own. I also tried doing it in code, but it is very verbose, and very easy to make mistakes. The visual format helps a bit, but most of the time I want to center my views, and there is no way to specify that in ASCII.

This is the time when I really really miss Android. The system was designed from day one to handle multiple form factors, and you are introduced to concepts like match_parent and wrap_content from the very beginning. I declare my layout in xml, spell out relationship among the the views with human-readable ids, and I can easily verify my rules whenever I need to add a view. In iOS I am always doubtful when I drop in a new view. What did it do to the existing views? It is so tedious to click through them one by one and examine all the constraints.

Perhaps there is a better way. But all my iOS developer friends started before iOS 6, before auto layout was available. They declare their views in code, compute the frames by hand, and basically run their own layout algorithms. And there is no reason to convert once you have a system in place, so I am on my own on the auto layout front.

Intents

Another thing I miss about Android is the intent system. Both for navigation and integration.

Navigation

For Heart Collage, I capture your poses with the camera, then replace the camera activity with the view collage activity, showing the mosaic. Here is what I do in Android:

Intent intent = new Intent(this, ViewCollageActivity.class);
startActivity(intent);
finish();

In other words, I add the view collage activity onto the activity stack, and remove the camera activity by calling finish().

It took me a very long time to figure out how to do that in iOS. In storyboard, most of the time you push a new view controller onto the stack by adding a segue to a button. You can also push a manual segue, which is what I do after the camera snaps all the photos. The tricky part is, how do I pop the old view controller? If I push first, the old view controller is no longer on top on the stack, so you cannot pop it. If I pop first, the old view controller is no longer on the stack, and I am not allowed to ask for a segue from it.

This is the moment when I doubt if it was wise to go with storyboard. It seems to be designed for very simple navigation needs, and even my 4-screen app is too complicated for it. I ended up popping one level higher with a flag to automatically forward me to view the collage. Bit of a hack, but I was too far deep into storyboard to back out and recreate all the views in xib. Especially since I have no way of copying and pasting the layouts, so I have to drag and drop everything again.

Integration

After you make a Heart Collage, the app lets you share it with your friends. This is super easy on Android. I just create an Intent saying that I want to share an image, and the system automatically generates the list of installed apps that can handle that. It’s an elegant way to have a personalized and extensible experience. Users can share their collages with any apps they prefer, and I don’t even need to know they use that app, let alone creating a new integration point.

For sharing, iOS 6 provides a similar functionality with UIActivityViewController. I set up the message and image, and it brings up a list of options for sharing. The big difference is the list is curated by Apple, and not extensible by the user. So everybody will see Sina Weibo as an option, whether they care about it or not.

This is where Android really shines, the seamless integration among apps, and as a result a very personalized experience.

Distribution

Beta testing

Finally my app was ready for beta testing. Yay!

Here are the steps for both platforms:

Android

  1. Compile the apk
  2. Email it to some friends
  3. There is no third step

iOS

  1. Collect UUID from friends
  2. Create provisioning profile from iOS dev portal
  3. Add UUID for each new test device
  4. Download provisioning profile from iOS dev portal
  5. Compile ipa
  6. Email provisioning profile and ipa

The most painful part is that I have to manually add each test device on the provisioning portal, and then download it to my local disk to compile the ipa. So tedious.

The flip side though, I know exactly who can run my app, and I don’t need to worry about leaks. For Android, once you send out an apk you have no idea where it will go. And there isn’t really a good way to limit the distribution.

Release

And now, the final moment - release to store. No anxiety for Android at all. Just upload, wait for an hour or so, and it’s live. For iOS, there is the review process.

I want to release Heart Collage before Valentine’s Day, so I submitted at the end of January. There should be plenty of time, but the potential rejection was stressing me out. I was so relieved when the app got approved the first try, in 6 days. Jubilation!

Verdict

I have been mostly pointing out the difference between iOS and Android. But at the end of the day, they are more similar than different. In terms of technology, at least. The verdict is still out on the money. Is it true that iOS users are more willing to pay for apps? Which platform will generate more revenue? That will be the driving force for my decision to spend time on iOS vs Android, and the numbers are still out. Will Heart Collage get more downloads on iOS or Android? We shall see.

Many thanks to Cyril Mottier and Tim Burks for reviewing the draft of this article.

Wanna check out Heart Collage? Download it here:

Friday, February 1, 2013

Heart Collage launched

Super excited that I just launched my app Heart Collage, just in time for Valentine's Day!

The app shows you how to pose for each part, snaps the shots one by one, and stitch them all together into a Heart Collage. I love watching people pose for the various parts of the heart - it's hilarious!

Get the app from Google Play or Apple App Store, and let me know what you think!

Monday, February 27, 2012

iOS programming first impressions

I learned iOS programming for the BeMyApp Hackathon, and finally got a chance to experience Objective-C first hand. With just two days I only managed to learn one particular way to do a task, so some clumsiness are mine. Nonetheless I'd like to jot down my first impressions.

Square brackets

Before the hackathon, the only thing I knew about Objective-C was that there are a lot of square brackets. That's the syntax for passing messages. I didn't have time to learn the difference between function calls and message passing, and I need to look into that. But otherwise I don't really see why people make such a big fuss out of it. Yes, it's clumsy. But conceptually it doesn't seem too complex. For me, I keep forgetting how to define a function with parameters, so I had to refer to the existing functions. But I'm sure I'll get used to the syntax in no time.

Specifying UI components

When I picked up Android, the visual UI design tool was still in its infancy, and not very usable. As a result I always specify my UI via XML. In iOS, however, I had to use the visual tool. There is a list of UI components on the side bar, and I drag and drop them onto the screen designer. I like that there are helper lines to match up elements horizontally and vertically. But then I had to add 5 buttons, and I wanted to space them evenly. That was no obvious way to do it. I went into the source, but everything has absolute co-ordinates, unlike Android, where I can specify the relative positions and use margin to space them out. Since it was just for the demo, I placed the buttons roughly where they should be, and moved on.

Linking UI components with code

Next I needed to hook up the buttons so they do something when you click on them. The basic idea is the same in iOS and Android: you define a click handler, and link the button to it. In Android, you can do the linking in two ways: specify the onClick function in XML by name or assign an ID to your button in XML, and do the association in Java code.

In iOS I only learned one way:

  1. Define a function in the ViewController class with the signature (IBAction)foo:(id)sender;
  2. Open the graphic editor for the xib file.
  3. Right-click and drag the button to the icon of the ViewController.
  4. All the IBAction functions will be displayed. Choose the one you want.

I'm not familiar with the right-click and drag gesture, so this feels a bit clumsy. But it's not a big deal.

Project files

The biggest pain point is actually the project files. Like any sensible team we use source control to share code. But it wasn't clear which project files need to be checked in. And when we add a new class the project files change in some opaque way. I spent so much time helping team members deal with git merges that it was getting a bit tedious.

Device deployment

This is even more tedious than git merges. We have to collect UUIDs from all the devices of our team members, create a list, embed that in the build, etc etc. Android is much simpler - just distribute the apk file. The flip side is that you cannot control who gets to install your Android beta binary, so each platform has its own annoyance.

Conclusions

A lot of people complain that iOS programming is really difficult. So far I don't feel that way. If you have only done Ruby on Rails or javascript, it can take a while to get used to memory management. Things are a bit more verbose, the UI is specified in a quirky way, but nothing too bad. Maybe I'll start screaming once I get really deep into it, but so far so good :)