1

In the WWDC 2013 talk on processing app store receipts, it is suggested that for iOS apps, receipt validation code should be called as soon as possible. Even before application:didFinishLaunchingWithOptions: - i.e. in the main() function. I suppose that the way this would work is as follows:

int main(int argc, char *argv[]) {

    @autoreleasepool {
        validateReceiptMethod(); // <---- HERE
        int retVal = UIApplicationMain(argc, argv, nil, nil);
        return retVal;
    }
}

The idea is that the UIApplicationMain() method is what launches your app and calls application:didFinishLaunchingWithOptions:. If you put the validateReceiptMethod() after UIApplciationMain(), it would never run.

Anyway, this is working great. But what if there is no receipt? Then you need to call SKReceiptRefreshRequest to get a new one from the app store, which is fine. But if you run this code before UIApplciationMain(), it will also run before any of your UI is displayed. So what would happen in terms of showing the user the apple ID login dialog? Is it even possible to call SKReceiptRefreshRequest from the main() method?

Jason
  • 14,517
  • 25
  • 92
  • 153

1 Answers1

2

So what would happen in terms of showing the user the apple ID login dialog?

Store Kit alerts appear in windows that are not owned by your application, so can be shown when your application is not active — even before it launches. But this is not really relevant.

Is it even possible to call SKReceiptRefreshRequest from the main() method?

This may be possible if you set up your own event loop then stop it when the receipt request finishes, but you should not do this. Don’t delay launching your application waiting on a network request; it might never complete. If the receipt is invalid, I would recommend entering UIApplicationMain() and requesting another receipt when launching finishes.

Edit: Since you can not do anything about not having a valid receipt before entering UIApplicationMain(), I don’t understand why Apple recommends checking at this point. This makes sense on OS X as the application should terminate, but not on iOS where application should keep running and it is acceptable to ignore invalid receipts. You could check early, store the state in a global variable, then respond later; but why not check only when you’re ready to respond.

Douglas Hill
  • 1,537
  • 10
  • 14
  • That's a good idea. `validateReceiptMethod()` could return an INT based on what happens (e.g., 0 if receipt is invalid, 1 if it is valid, -1 if no receipt found). Is there an easy way to pass that return variable from main() to `application:didFinishLaunchingWithOptions:` so that when that method is called, it will know (without having to validate the receipt a second time) that there is no receipt and thus it should calls `SKReceiptRefreshRequest` and get a new one? – Jason Dec 05 '13 at 21:15