Proper storage of In-App Purchase - iphone

Are there any recommendations how to store in-app purchase results.
I made purchase using
raywenderlich tutorial
It stores the result to NSUserDefaults.
So the question : Is it safe to store the in-app result as a bool value in NSUserDefaults. Because everyone can look in Library/Preferences folder and see what is written there.

Yes, this should be OK, but it may depend on the app. Most "normal" users aren't going to be poking around in your Library/Preferences file. So if you're writing an app for a mainstream audience (average to low technical knowledge), NSUserDefaults is a safe place. You also have to consider people's time value. If your app costs 99 cents, it's probably faster to buy it than to go hack some prefs file. If your app costs $99, there's an incentive for some people to go looking for hacks.
So If you're writing a super expensive app, or an app for a hacker/developer audience, you may want to store your result in a Keychain or something more secure.
I have personally used a simple "hasUpgraded" BOOL stored in NSUserDefaults, and never had a problem.

Related

Where should I store data that needs to persist for a given appleID?

The answer to this question may be iCloud storage, but I am using this for a very light-weight piece of data and think it may be extreme to use iCloud for this one purpose. We have an in-app subscription app. Before we provided the app for free but would not deliver any content to it until the user subscribed to content through the in-app subscription.
Some reviews indicate people think that we are trying to trick them by saying free and then saying they have to subscribe. We want the app to be listed as the price of the subscription to avoid this misunderstanding but after the first year has elapsed offer them the in-app subscription to continue. We plan to store the initial launch date in persistent storage so that we can determine when to begin requiring a subscription receipt.
1) We wanted to use the keychain storage since this information will persist even if a user removes the app from his/her device and then re-installs. The problem is if the user gets a new device and does not restore it from an encrypted backup, then the initialized value will be lost.
2) If we use our servers to store this value for them, then there seems to be no way to tie it to that appleID; so that is ruled out as a possibility.
3) Back to iCloud, it just seems like a lot to add iCloud support just for this, and I believe the user still has to have iCloud enabled for this to work.
Does anyone know the solution to this data persistence problem? Help is appreciated!
Yes, nsubiquitouskeyvaluestore is the way to get it synched with new devices. Using this in conjunction with both keychain for storing on a device after app as been removed and nsuserdefaults for quick and easy unconstrained access is the way to go. Apple also has a way to read receipts for the actual app purchase now, but it only works for iOS 7. Solutions should conditionally rely on receipt data from nsbundle.mainbundle url if it is available.

Do apps need to ask user preference in order to use iCloud for simple data?

We are currently working on an app and would like to sync favorites across devices using iCloud. The favorites are fairly lightweight and text only. Do we need to ask the user for permission to use iCloud or can we simply go ahead and use iCloud if available?
I have setup all iCloud syncing code already. So it is more a question about AppStore submission rules. Any experiences?
Apple guidelines state that you should invite the user to use iCloud, and give them the choice as to whether they want to use it or not. (Documentation, see "Prepare Your App to Use iCloud").
As per the App Store Review Guidelines, there isn't a concrete rule that states you need to do this, it's more of a guideline and a courtesy. I'd suggest you do though, it provides a better user experience, and happy customers.
Why should I need permission anyway?
Users only have a limited amount of storage (typically the 5GB allowance), and it's up to them how it should be used. If all applications decided to use iCloud without permission, it'd be a free-for-all, and space would be eaten up fast.

How to offer non-consumable content for in app purchase?

I am developing an app for learning piano and I would like to offer lessons as non-consumable in app purchases. All of the files that are required for the lesson will be bundled with the app (as they don't take up a ton or space; two PDFs, a .mid, and a .png). Currently, for testing purposes, I have just been hard coding the lessons into my app and they get loaded on viewDidLoad.
My question is how can I store a library of lessons that I can modify when a purchase is made to show that it had been purchased? Essentially, all I want to do is when a completed transaction is received, the value of purchaseStatus will change from 0 to 1.
The stored data consists of a number of strings, NSNumbers, and an array of NSNumbers.
I have seen a few options such as plists and NSUserDefaults but I'd really appreciate some advice on the best way to go about it.
Thanks in advance :)
I would say storing the purchase status of each purchasable module in an NSDictionary that you store in NSUserDefaults would probably be the most straightforward/simplest option. Every time you launch the app, query this dictionary to determine what has been purchased and accordingly reveal those purchased entities to the user (in the form of an entry in a table view, an icon, a no longer hidden button, etc.).
Plists are fair game as well, but it would require a bit more maintenance (where to store the plist so that it may be backed up by iCloud, etc.) whereas NSUserDefaults has that all taken care of for you (it's backed up by iCloud).

StoreKit: can I offer a user a free download for a product of his choice that normally costs?

I'll soon have to implement the StoreKit functionality and I was wondering...
is there a way to also offer a product for free to a user once, like as a gift for using the app for the first time ?
In my special scenario I'll offer several products in my educational app, which the user will need to buy time by time, if he is interested in continuing to learn with the app.
But the first product I want the user to have for free and it should be his choice which one he takes. So generally all products should have a price, but the first download shall be free.
And I want this to get logged on my server so I can reidentify him, so (A) he can't delete the app, reinstall and download yet another free product and (B) so he will also get the products on any other of his devices.
I'm also open to workarounds, like maybe get something similar to the apple id or so, to be able to store it on the server. I know that I could also use the [[UIDevice currentDevice] uniqueIdentifier], but I want the user to have this first free product on all his devices, and ONLY ONE.
Is there a way to get (A) and (B)?
Apple's In-App Purchase infrastructure (and by extension, StoreKit) does not support free content.
But there's nothing stopping you from providing free content via your own mechanisms, as you surmise. You would have to do all the tracking yourself in terms of remembering device IDs on a server somewhere, and noting that device != user, so would miss some edge cases.
You don't get access to (iTunes) user data at all, so you probably can't guarantee the "only once" across multiple devices, unless your app has an associated backend service account that is already unique per user.
(Before building infrastructure for this, you should double-check the developer agreement/contracts on this stuff. You're not circumventing Apple's revenue stream here, which is good, but what you're talking about may be unusual enough to raise a flag with them in terms of experience consistency if nothing else.)

iPhone In-App Purchases for Free-Trials

I am in the process of releasing an application to the app-store. I recently saw that you can make your application free but have in-app purchases. When I saw this I thought that this could be used to create a free trial. However in Apple's Helpful Tips for Using In App Purchase In Free Apps it says
Don’t set time limits on any of the
functionality of your app, either for
run times or life times. Applications
that only run for a set number of
minutes per session, or that expire
altogether after some period of time,
don’t recruit customers so much as
leave a bad taste in their mouths.
I know that sometimes it's tough to know what Apple is thinking but does this mean they will not allow In-App Free Trials or that they frown upon it. Does anybody know if people have tried doing this?
As indicated in your quoted text, they will reject any app that is a "trial" in that it only works for a limited amount of time or number of uses.
If you want to remove advanced functionality and allow users to pay for them, that's perfectly acceptable. In fact, it's one of the main use cases they talk about. Just keep in mind that the free version of the app (before people pay for the advanced features) should do something useful, and it should not expire.
Also, something to watch out for is "placeholder" functionality, which will get you rejected. For example, if you make a game and have difficulty levels that must be purchased, you can't make it look like those difficulty levels can be selected and then prompt the user to pay for them once they try to select them. You can tell the user that there are missing difficulty levels and encourage them to upgrade, however, which is a subtle but important distinction.