Monday, November 14, 2011

Apple and non-public APIs

We recently got a rejection from Apple for using a non-public API. Google was not a big help on this one, so here's the story of how we tracked it down.

We found that your app uses one or more non-public APIs, which is not in compliance with the App Store Review Guidelines. The use of non-public APIs is not permissible because it can lead to a poor user experience should these APIs change.

We found the following non-public API/s in your app:

appName
setAppName:
Step 1: Find in files

There's a dropdown when typing into the search bar in XCode that lets you search in frameworks. Unfortunately we got no hits with this search, so that tells us the private calls are not in our code.

Step 2: Command line tools
From the rejection mail:

Additionally, one or more of the above-mentioned APIs may reside in a static library included with your application. If you do not have access to the library's source, you may be able to search the compiled binary using "strings" or "otool" command line tools. The "strings" tool can output a list of the methods that the library calls and "otool -ov" will output the Objective-C class structures and their defined methods. These techniques can help you narrow down where the problematic code resides.

otool and strings are tools that seem to be on the global path, so you can type them into the command line from any directory. The trick is you have to figure out what to run them on. XCode 4 tends to put things in strange directories, so here's a shortcut to finding the actual file you want.


Find your app under "Products" in XCode and right click on it to select "Show in Finder". This will open up a finder window where your .app file lives. If you run otool or strings on this file it will not work. Right click on your .app file and select "Show Package Contents". Then find your executable file and copy it to somewhere accessible.

Once in Terminal and in the right directory, the two commands to use are:
otool -ov ScribbleWormHD
strings ScribbleWormHD
These will output a ton of stuff. You likely won't be able to navigate it without using command-F to search for the strings that Apple complained about. In our case otool did not give us anything useful. It would have been easy to track down the problem if it had, because otool will tell you what called the offending function. Strings just outputs a list of every string used in your project. We managed to get a hit with that, so at least we had a way to test if any changes we made would fix the problem.

* NOTE: strings did not work for us at all in Snow Leopard. It only worked in Lion.

Step 3: Head Scratching

So the calls to setAppName were not in our code, and we had no tool telling us directly where the calls were. Sometimes debugging degenerates into informed trial and error. We only have two middleware libraries in Scribble Worm: Flurry and Admob. We started with Flurry on a hunch and removed it from our project as a test before running strings again. This time we were clean.

So we went to the Flurry site and found that they are on version 3.0 while we shipped with 2.8. One upgrade later and another run of strings and we were ready to submit.

1 comment: