Friday, May 25, 2012

How Rogue Amoeba's Airfoil Speakers could get pulled from the App Store for using a non-private API

Apple says Rogue Amoeba's Airfoil Speakers was pulled from the App Store for using a private API.

To recap, using a private API is sure to get your app rejected from the App Store. Unless Rogue Amoeba open sources their app, no one knows for sure if they're using a private API. I believe them when they say they aren't using one. But there is another way to get in the situation they're in.

Let's say an app developer unknowingly uses an API that was previous not flagged as private. Perhaps it's a publicly "known" API, even an open secret, but technically not part of the public API set. Your app passes the automated private API check and gets through manual review. A little while later, Apple adds the previously not-private API you used to the catalog of private APIs. Perhaps Apple realized their oversight, and given how serious they are about apps not using this API, ran an automated check against all App Store apps for usage. They discovered that Airfoil Speakers used this private API. Clearly they choose to pull the app in this case.

I offer this possibility because something similar happened on a project I was working on. A number of versions of the app had been approved and where for sale on the App Store when a small bug fix release was stopped cold during App Store manual review for private API use. The team was mystified at first and insulted, we hadn't used any private APIs, and had barely changed the app, what gives? But we did use a private API without even knowing it. The app used MAZeroingWeakRef for weak pointers, almost exclusively for delegates, but also for KVO notifications. Turns out the version of MAZeroingWeakRef we were using was intercepting a private API call!
@interface NSObject (KVOPrivateMethod)
- (BOOL)_isKVOA;
In a later version of the library, there was a #define to not use that API. We turned it off, the app came crumbling down with memory issues. It was not a fun few days working to solve all the memory management issues MAZeroingWeakRef had hidden from view when there was a critical bug fix update to ship.