In part 1 I wrote up a method of finding out what version of your iOS app a user originally installed that works great, provided you can get a network connection and the App Store servers are up.
But if you can’t rely on that being the case, and you don’t want to wait for it to be true before you take whatever action you’re basing on the original version number, you can get the receipt data locally and process it.
So, for whatever reason – lets say that you want to experiment with a free download and IAP monetization model in an existing paid app but you don’t want to double charge existing users, or maybe you need to do some clever user defaults or data model updates – you decide that you need to know what version of your app was originally purchased.
So far as I’ve been able to discover so far, there are basically two ways to go about this. Well, one way, but there are two ways of getting the data. Well, N ways actually, but let’s not get all forked up at this point. This is (one possible implementation of) the easy way.
Assuming you have a receipt (and you may well not, in your dev version at least, in which case you need a bit of SKReceiptRefresh magic) then you can find it in your app’s bundle, and (assuming you have some network connectivity, and can talk to it) you can fling it at the App Store servers and they’ll parse it for you and fling back some JSON.
It looks a little like this.
Before I show you the one weird trick, a caveat or two. There isn’t a framework method anywhere to do this, and while this code doesn’t involve touching any private APIs it does have a number of other issues. From an app store review perspective, it could easily be argued that if Apple wanted you to be able to detect this stuff, they’d have put an API in for you. While I do intend to try it out, I suggest that if you do use this code in a production app you ready yourself for rejection and have a backup plan. From a technical point of view, it seems likely that you will need that backup plan as this possibly rather less than robust. I’ll get to that in a minute, you want to see the code now right ?
I like C blocks and I cannot lie. Which is just as well, really, since so much of the iOS SDK is built that way. They don’t come without their own idiosyncratic set of problems though, one of which is that so much of the iOS SDK isn’t built that way. Maybe it’s just my bog standard codemonkey OCD spiking, but I sometimes find that when I’m deep into some bit of block based coding and going all data flowy and functional, dropping back to the objecty world of message passing and delegate protocols at an inappropriate point in my flow can lead to a lot of mental gear grinding and lo, gnashing of the teeth.