Rejected

I was hoping I’d never have to write this blog post.

The 2.0 update to my iPhone app, Flickit was rejected by Apple. In order to get the update approved, I had to remove some functionality, and a month later, version 2.0 has finally made it into the App Store. If you’re wondering why some of the features you’re been accustomed to are now missing, here’s why.

This is also a cautionary tale for other iPhone developers. I was certainly caught by surprise by some of the reasons for this rejection, so hopefully I can save other devs some unexpected headaches.

First, let’s take a look at what Apple’s reviewers had a problem with. The iPhone SDK has a nice, easy to use, pre-packaged user interface for picking photos from your library - UIImagePickerController. You’re probably familiar with it. It looks like this:

Standard UIImagePickerController

All 3rd party apps have to use this standard UI in order to get access to the photo library.

One of the problems with the buit-in UI is that it forces you to pick one image at a time - there’s no facility for multiple selection. What this means for my app is that if a user wanted to upload several photos at once, they’d need to open the UIImagePickerController’s screen for every photo. This can become tedious fairly quickly if you wanted to select a more than say 2 or 3 photos. In Flickit’s initial release, this is how it worked, and it was something people complained about right away. I started thinking about ways to work around this limitation and allow users to select several photos at once without having to re-launch the UIImagePickerController. The solution I came up with looks like this:

My UIImagePickerController

As you can see, I added a couple of things to the UI. I added a toolbar at the bottom that shows the number of photos you’ve already picked and a ‘Done’ button that lets you complete the selection and dismiss the picker UI. I also added a little progress indicator overlay on top of the photo grid. The overlay displays an activity indicator while it’s processing the selected image, then briefly shows the checkmark you see in the screenshot. After that, it goes away.

The rejection notice specifically called out these modifications. Here’s the email I got:

Thank you for submitting Flickit (Flickr uploader) to the App Store. Unfortunately it cannot be added to the App Store because it is modifying or extending an undocumented API, which as outlined in the iPhone Developer Program License Agreement section 3.3.1 is prohibited:

“3.3.1 Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs.”

There is no documentation for creating custom subclasses of UIImagePickerController, the organization or layout of the view hierarchy managed by UIImagePickerController, and any of the custom classes managed by UIImagePickerController in iPhone OS 3.0.1.

Specifically, the the organization and layout of the image picker view hierarchy is undocumented. Please refer to the attached images.

Now, there are several interesting things about this rejection when you consider the app’s history, competitors, and details of Apple’s policies. Let’s take a look:

7 strikes and you’re out

The first interesting thing is the fact that this wasn’t a new feature in this release. It had been there for a while, and passed approval through several updates. In fact, this same UI had been in the app through 6 updates that were all previously approved. Lesson learned #1:

Past approvals don’t guarantee future approvals for the same feature

It strikes me as a bit odd that it would be approved so many times before and then suddenly catch their attention. Were the App Store approvers just missing it the first 6 times? Was this a new policy going into effect recently?

One possibility that occurred to me is that Apple might be taking a risk-based approach when scrutinizing apps for approval. With hundreds of app submissions a day, and only a small team of approvers, it’s no surprise that the approval system has quickly become overwhelmed. Perhaps Apple has made the decision to review some apps more closely than others? How would you decide which apps to let through with a quick glance and which to take a closer look? Impact on number of end-users seems like a good metric. Perhaps the review process takes into account the number of people that have installed the app, and then more closely examines apps that will have an impact on a large number of users. Flickit is no chartbuster, but by this point it had already been out for close to a year and has a somewhat sizable install base. That could explain why the app only got rejected now. Of course this is only speculation, but it seems plausible given the next lesson:

Consistenly inconsistent

The reviewer’s primary concern was the overlay message on top of the photo grid. Apple doesn’t want you messing around with the built-in views of the UIImagePickerController. Out of curiosity, I took a look at the official Yahoo Flickr app. This is what they do when you select an image:

Flickr UIImagePickerController

A smaller overlay than mine, but effectively the same approach: Briefly show a progress indicator while processing the selected image.

This next bit really threw me for a loop. On the same day, I submitted two apps. One was Flickit 2.0, and the other was Flickit Pro. Flickit is a strict subset of Flickit Pro. In fact, Flickit’s entire UI is copied into Pro’s feature set as a separate tab. Both apps have the exact same modifications to UIImagePickerController that I mentioned above. Flickit Pro was approved, Flickit was rejected. I specifically asked Apple about this, but didn’t get an answer. Lesson #2:

Approvals of identical features in other apps is not a barometer for approval success of *your* app

It’s bad enough when there is inconsistency in applying the rejection criteria across different apps, but when the exact same functionality is approved in some cases and not others, it’s really baffling and frustrating.

Intentional consequences

This whole thing would be a lot easier to accept if I was deliberately trying to get away with a hack that I knew was violating the approval guidelines. Even if I unknowingly violated a policy that I at least understood, that would be OK with me too. I’d fix it and move on.

The irony here is that I was well aware of this policy, and took a lot of time and effort to ensure that I didn’t violate the policy of using undocumented APIs. In general, I think Apple’s crack-down on developers’ use of hidden APIs or modification of built-in UI is actually a good thing. If developers start building apps that do these things, then it makes it very difficult for Apple to make improvements to the implementations of these system components without breaking a lot of apps. It makes the whole ecosystem less stable, and isn’t good for Apple, developers or app users. A perfect example was when Apple introduced video capture features in iPhone 3GS. The UI for UIImagePickerController added a bunch of controls for handling video capture. If your app made assumptions about the layout of the controls on the camera, then it probably broke when Apple released the update for video capture on the 3GS.

I knew I didn’t want to make assumptions about the implementation of UIImagePickerController so I didn’t implement anything that did. I knew my app would break if UIImagePickerController changed in future iPhone OS updates.

After my first rejection notice, I started trading emails with a very patient and friendly engineer from Apple’s Developer Technical Support team to try and explain my implementation and make an argument for why I didn’t think I was violating their policy. A few dozen emails later, I was still not able to convince him that my app wasn’t making any assumptions about undocumented APIs.

It’s hard to communicate this stuff over email. Subtle technical details sometimes don’t translate clearly into paragraphs of prose. I have no doubt that if we were in front of a whiteboard I could draw a few pictures that would make my arguments a lot clearer. Lesson #3:

Don’t rely on cute workarounds, even if you think they’re “legal”

Another thing fueling the confusion is what seems to be a hyper-sensitivity on Apple’s part for anything that touches the camera or photo library UI. Maybe too many users got hit with broken apps after upgrading to iPhone OS 3.0 with the video camera updates?

Endgame

The message from Apple was loud and clear: Don’t mess with UIImagePickerController.

I decided it wasn’t worth the effort to continue my arguments for why I thought my app was built within the boundaries and the spirit of their guidelines. I had other new features and bug fixes that I wanted to get released in the update, and continuing the emails back and forth would only prolong the release even further, without a clear outcome.

I removed my “enhancements” to the UIImagePickerController, re-submitted the app and it was approved a week later.

I’m now preparing myself for the inevitable backlash of users who will miss this feature and complain about it being removed. (If you’re one of those people, I’m sorry!) Adding new features is easy. Taking them away always ends up making somebody angry.

Another thing I’m not looking forward to is trying to explain to customers why other apps have this feature, but mine does not. Most customers don’t care about “Undocumented APIs” or the intricacies of Apple’s app approval process. If someone sees a particular feature in another app it’s only natural to think another developer should be able to implement something similar. I wouldn’t blame anyone for thinking I was trying to blow smoke with some of these explanations. It’s a tech support nightmare.

This experience hasn’t exactly been great. Has it affected my opinion of the App Store in general or plans for future apps? I’m not sure yet. Flickit Pro is kind of a litmus test for me and my future plans for developing iPhone apps for my company. The jury is still out on whether my investment will pay off or not.

One thing’s for sure: In the future I’ll definitely think twice about implementing any workarounds for limitations in the iPhone OS.

blog comments powered by Disqus