Skip to content


On the Postage Rejection

Note: A technical post follows. If you’re not interested in iPhone programming, you can safely ignore it.

Technical Analysis
An update to RogueSheep’s Postage app was recently rejected by Apple because of a supposed overriding of a private method in a category. Apple most likely used a static analyzer to determine this problem. As far as I can tell, Apple has a bug in their static analyzer.

Three20 adds a category method -previousViewController to the UIKit class UIViewController. According to RogueSheep:

The notice from Apple indicated that we had used a private method of UIViewController called previousViewController.

As far as I can tell, there is no private method in UIViewController called -previousViewController. There is, however, a private method on UINavigationController (a subclass of UIViewController) called -previousViewController.

However, this should not be a problem. Subclasses of UIViewController which implement -previousViewController themselves will override the category method defined on UIViewController by Three20. This includes UINavigationController and whatever other Apple-defined subclasses exist for UIViewController.

I have filed this as Radar #7414099 (rdar://7414099 for Apple employees). The test project is available at: CategoryBehavior.zip

Opinion
Ultimately, if my analysis is correct, this is just a bug. They happen. Static analyzers are especially difficult to get right, especially when the source isn’t available. This shouldn’t be read as an indictment of Apple, or of Apple’s intentions. They’re just trying to protect the user experience of their products and head off binary compatibility problems.

However, I personally think they’re going to have a difficult time trying to detect private methods with a static analyzer. They might have better luck doing analysis at runtime — checking the actual class hierarchy and interposing on method calls.

Meanwhile, there will be a lot of false positives caused by this, which is going to be frustrating for a lot of iPhone app developers.

Posted in Miscellany.

Tagged with , .


6 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Kevin Ballard says

    The one thing I haven’t seen anybody mention yet is the fact that overriding this private method could have implications for the behavior of UIViewController. Unless the overridden implementation of -previousViewController behaves identically to the private one, any Apple code that calls this method may start failing.

  2. andrew says

    Hi Kevin:
    As I point out, as far as I can tell there isn’t an implementation of -previousViewController in UIViewController. So, there aren’t any implications for this category on Apple code.

  3. Louis Gerbarg says

    There are actually ways this could impact the existing Apple code. For instance, it is entirely possible some of Apple’s code could be doing a [vc respondsToSelector:@selector(previousViewController)].

    While that might seem somewhere atypical, the whole notion of how view controllers are related to each other (as opposed to views) is somewhat ad hoc and ill defined, so it would not shock me if the collection VCs (navigation controller, tab bar controller) have some internal protocols for things like next and previous VCs that other parts of UIKit call when present by checking if VCs respond to them.

    IOW, just because you are adding a method didn’t exist previously doesn’t mean it won’t cause runtime changes. We live in a very dynamic world 😉

  4. andrew says

    Louis: Hah, fair enough, you got me there. That would still be some pretty smelly design on Apple’s part though.

  5. Louis Gerbarg says

    Yes, but quite frankly, the view controller hierarchy reeks. Everything to do with collection view controllers is pretty hacky, and it actually is not possible for 3rd parties to implement them because Apple doesn’t expose setParentViewController:. I spent quite a bit of time disassembling them and looking at what was going on before I decided it was impossible to do what I wanted and implemented my own view controllers from scratch rooted off of UIResponder.

  6. Oskar says

    We just got rejected for use of private API “setThoroughfare:”
    This is indeed a private API in MKPlaceMark in the MapKit. The thing is that we never call this in our code.

    What we do have is an attribute named “thoroughfare” in a Core Data class. setThoroughfare is generated from @dynamic.

    Does this imply that all attributes in all core data classes must have names that in no shape or form resembles an attribute found in any of the private API’s?



Some HTML is OK

or, reply to this post via trackback.