I got an App Store Rejection

I am an iOS developer by profession. Recently, I decided to pursue an idea of my own and at the same time diversify my skill set. Ergo, I decided to build my first Mac App. So I quit my job and started working on my idea. After a few months of hard work on the Mac App and the website and a few hiccups, I was ready to submit the app to app store. Praying to god for good luck but also slightly dreading the worse, I pressed the Upload button. Three days later, lo and behold! I was staring at a REJECTI@N from Apple for these reasons:

    2.1: Apps that crash will be rejected
    2.21: Apps may not use update mechanisms outside of the App Store
    2.5: Apps that use non-public APIs will be rejected

Bad news I said to myself. But not only was I determined to push the app through, I already had the roadmap for the next version ready. There was no way I was going to let this setback slow me down even for a moment. I sat down and rectified the errors as follows:

2.1: Apps that crash will be rejected

There were two crashes noticed by Apple and they had attached the crash reports for debugging.

  1. Looking at the logs, Crash1 happened due to NSPortTimeoutException when NSSpellChecker class is used by the app for the first time after system start. I was using it to give users auto-suggestions as they start typing in a textfield. In my code, I was doing my own exception handling using the ExceptionHandling.framework. I changed my
    - (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldHandleException:(NSException *)exception mask:(NSUInteger)aMask{
            
    }
    

    method’s implemetation. That fixed it.

  2. Crash2 was related to MASRecieptValidation workflow. The app checked for the presence of a valid MacAppStore receipt stored in ExpenseTrack.app/Contents/_MASReceipt. When an app is downloaded from the Mac App Store, this receipt is installed by default and receipt validation succeeds. But while Apple was reviewing it, this receipt was absent and the app exited with exit code 173. During my testing, I created a test account on iTunesConnect to generate a dummy receipt. I said Apple that if they wanted to test the dummy receipt generation/validation workflow, they can followed these steps:
    1. Kill storeagent using killall -KILL storeagent (without this, the sign in prompt was not showing. Please refer to http://furbo.org/2013/10/21/mac-app-store-receipts-and-mavericks/ for more details).
    2. Delete, install and launch the app.
    3. The app runs its receipt validation code which fails because the receipt is absent (this won’t happen when the app is installed from Mac App Store because the receipt will be installed by default).
    4. The app quits with exit code 173 signalling storeagent to get a valid receipt.
    5. Storeagent prompts users to sign in with Apple Id and fetches and installs the receipt in the ExpenseTrack.app/Contents/_MASReceipt folder and then relaunches the app.
    6. The receipt validation code succeeds because the receipt is now present.

    That fixed it.

2.21: Apps may not use update mechanisms outside of the App Store

In the app, I had provided a Check For Updates menu option to allows users to check for updates. Apple thought that through this option I was providing an update mechanism outside of the App Store. I don’t blame them because on the face of it, it appeared so. But it wasn’t as it looked. Here is how it worked:

  1. I upload an new version to iTunesConnect and update my back-end(server) with that version number once it goes live.
  2. The app when launched makes an http request to our back-end to check for the latest available app store version.
  3. The app receives and compares it with its own version. If received version > app’s version, it generates a Growl/NSUserNotificationCenter notification which when clicked launches the App Store app on the Mac using macappstore://myappurl. This loads the app’s page in the App Store app allowing users to download the new version.

So you see, it wasn’t as it looked. But I removed the option without arguing my case any further with Apple.

2.5: Apps that use non-public APIs will be rejected

This is what Apple said, “The app includes OBJC_IVAR_$_NSView._frame from the framework ‘/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit'”. This was a little unexpected. I somehow ended up using NSView’s _frame iVar (private iVar) directly in a subclass of NSView in my code. I used otool and nm as suggested by Apple to identify the culprit class and changed the iVar usage.

After these changes I was ready to go again. I hit the Upload button once more after saying my prayers of course. Three days later, lo and behold! the app was Ready For Sale. June 16th 2014, 10:56 AM was a happy moment for me. My first Mac app had been released. All the perseverance had paid off. I thanked god, heaved a big sigh, pat myself on the back and started work on the next version. I wish everyone Good Luck And Good Life!!!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s