I am currently implementing local receipt validation following Apple's Receipt Validation Programming Guide. I have defined a category on NSBundle
that conforms to SKRequestDelegate
and that offers a method for receipt validation, which I call from inside main()
before it initializes the application delegate and passes it to UIApplicationMain()
. This is what the documentation says:
Perform receipt validation immediately after your app is launched, before displaying any user interface or spawning any child processes. Implement this check in the main function, before the NSApplicationMain function is called.
When there is no receipt at self.appStoreReceiptURL
, my method for receipt validation prepares an SKReceiptRequest
with properties as follows and sets itself as delegate. Since it conforms to SQRequestDelegate
it implements both requestDidFinish:
and request:didFailWithError:
.
NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:
@NO, SKReceiptPropertyIsExpired,
@NO, SKReceiptPropertyIsRevoked,
@NO, SKReceiptPropertyIsVolumePurchase,
nil];
The odd thing is that neither of the two methods is called after the category starts the request while the app is running in the Xcode debugger. What could explain this? How can I receive (refresh) a receipt during development preferably with a category on NSBundle
? Is it perhaps to early to send the request before the application delegate has come into existence (despite of what the cited documentation indicates)? Is there any working sample code that I could consult?
It looks as if there were several reasons why this failed, the use of the category (at this time) being one of them. If I make the following changes I receive callbacks to
requestDidFinish:
and can make progress:Launch the app in the debugger on a physical device, not the simulator. Apparently StoreKit (and in-app purchaseses) will not work in the simulator. This is documented in Xcode 5.1.1 release notes.)
Let a object owned by the category (not the category itself) conform to
SKRequestDelegate
. (I would like to understand why this is an apparent requirement, but currently do not.)Retain both the
SKReceiptRefreshRequest
and itsSKRequestDelegate
during the entire duration of the request. Retaining either one but not the other is apparently insufficient. (Notice thatSKRequest
does not maintain astrong
link to the delegate.)