How persistent is [NSUserDefaults standardUserDefaults]? - iphone

I'm using [NSUserDefaults standardUserDefaults] for storing application settings.
My questions are:
do those settings are removed on app deletion?
are they kept after an application update (through the
AppStore)?
Because I'm using it to store a password and don't want my users to reset them at each update. Also, I'd like that the only way to reset the password would be to remove the app and re-install it.
Is NSUserDefault the right choice?
Thanks,
Jérémy

Yes, they are removed on app deletion and yes they are kept when an application is updated.
However, you're not advised to store sensitive data in the NSUserDefaults, instead I would look at using the Keychain.

I use NSUserDefaults in my app to allow additional access to my app for my colleagues. They just have to enter the code word in settings and the app is fully opened.
to the point each time I update the app they have to re-enter the code word, so I would say from experience that they are not kept after updates. The values need to be re-entered.

Related

Would the value of NSUserDefault lost after upgrade the app?

Would the value of NSUserDefaults lost after upgrade the app?
If I delete the app and reinstall it ,and then restore data from Itunes backup, would the value of NSUserDefaults lost?
You don't lose the value of NSUserDefaults when you upgrade the app.
When you delete and reinstall the app, though, you reset all the NSUserDefaults keys, so you can lose data (i.e. your score, etc).
Restoring from backup doesn't lose the NSUserDefaults value, due you've stored the value in iTunes and iTunes is giving you back again that value.
iCloud is the better solution unless you have some reason for not using it, and has the advantage of synchronizing multiple installations by the same user should you so desire.

Backing up NSUserDefaults and synching iPhone

Is the application domain in [NSUserDefaults standardUserDefaults] backed up when the user synchs their device? If not, can you suggest a close correct alternative?
Apple makes reference to "Application Preferences" in its documentation, such as regards in-app purchasing. I understand, perhaps incorrectly, that they're making reference to NSUserDefaults here although the terminology doesn't appear to match perfectly.
In-app purchases, which I plan to record in [NSUserDefaults standardUserDefaults], need to be backed up in my project.
Thanking you kindly in advance.
Yes. NSUserDefaults uses a PLIST file as a backing store, which is backed up on each sync. See http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/UserDefaults/Concepts/DefaultsDomains.html for more information.
If you wanted to see for yourself, you could check out ~/Library/Application Support/MobileSync/Backup/. Create an unencrypted backup of a device with just your app on it, and view the files in the PLIST editor.

force reset NSUserDefault on iPhone App upgrade

i want to force reset to NSUserDefault whenever user update my app. why i need this because every update include some new information abt user. as some info (token) already present in NSUserDefault my app does not call to my web service. due to that fact i dont have new user info. and also i dont want to write if..else statement for every new release.
thanks so much. hope my question is pretty clear.
Check this out:
[NSUserDefaults resetStandardUserDefaults]
For more info check the NSUserDefaults Class reference.
What you can do is save on the defaults the current version of your app. All the time that the user open the app you check the saved version against the current version. In the case of an update the current version will be different from the saved version, and so you know that it's time to clean the user defaults. After cleaned, you save the new value for the current version.
You can save your current application version into NSUserDefaults when you start up your application. Before doing so, you can just do a check to see if the actual application version is greater than the version stored in NSUserDefaults. If it is, you know that the user has just upgraded, and you can remove and information (such as the token) from the defaults using removeObjectForKey

How easy is it to hack a plist file in an app store app?

Don't worry, I'm not trying to hack someone else's app, if that's what you're thinking =).
I want to have 2 versions of my app, a free version and a deluxe version. My plan was to use an in-app purchase to enable the deluxe version by setting a boolean value in the plist file.
My question is: is this secure or is it easily circumvented? And if it is not secure, can someone suggest a simple alternative? I don't want to download additional content, I would rather keep all of the functionality within the app and enable it somehow.
Edit: I don't mean the application plist file, but something like the user defaults file.
You should store this in the keychain, this is what I'll do. The keychain is far more secure than a .plist or the user defaults (which are .plists, too, as far as I know). Have a look at SFHFKeychainUtils, you should be able to use this or just implement a better method exactly for the need to save a simple bool.
It is easy to edit the com.something.plist without jailbreaking. With a free tool* you can browse your device, you can also edit and save these files. If you store your inapp purchase something like this:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"com.example.pack1"];
[[NSUserDefaults standardUserDefaults] synchronize];
then this will be written to the plist:
<key>com.example.pack1</key>
<true/>
If you name your packages like this: pack1, pack2 etc., and somebody edits your plist (copy/pasting the first key), he/she could use the locked feature easily.
A not too hard to implement method would be to save like this:
[[NSUserDefaults standardUserDefaults] setValue:[self sha1ValueForKey:#"com.example.pack1"]
forKey:#"com.example.pack1"];
[[NSUserDefaults standardUserDefaults] synchronize];
where -sha1ValueForKey: is
-(NSString *)sha1ValueForKey:(NSString *)key {
return [self sha1:[NSString stringWithFormat:#"<SALT>%#", key]];
}
You have to change <SALT> to something.
You can find -sha1: here: http://www.makebetterthings.com/iphone/how-to-get-md5-and-sha1-in-objective-c-ios-sdk/
After this you can verify if the key matches the hashed value.
If somebody wants to hack your plist he/she has to know your hashing mechanism and salt.
This is not the safest way to protect your application but it is easy to implement.
*iExplorer
EDIT:
The suggested method only protects - somewhat - your IAP if the user doesn't have access to the hashed value. If someone gets it from somewhere, it is easy to copy that data to the plist. If the SALT is device dependent copying is useless.
I would recommend reading up on verifying in-app purchases. It sounds to me like you are trying to roll your own in-app purchase verification system which may be wrought with issues you might not have thought of yet. You have to be careful with your user's purchases that they will behave the same in your application as they will in any other, lest ye lose their trust (and future sales!)
Instead of worrying about the Info.plist file, why not just set a preference? Somewhere in your code, this would give you your boolean value:
[[NSUserDefaults standardUserDefaults] boolForKey:#"someKey"];
If the value doesn't exist, the result will be nil. This code sets the value:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"someKey"];
Plus, these values will be backed up in iTunes, so if the user moves their backup to a new iPhone or simply restores from backup, the values will be restored.
I don't have an answer, but it seems that editing your plist file dynamically is not possible, if I trust this subject :
You can not edit you're info.plist
file dynamically. When you submit your
app to The App Store, your app bundle,
which includes info.plist, can't
change because the signature created
when you compile you app is based on
the bundle.
Any pirate has a jail-broken iPhone
Any jail-broken device offers full file system access via tools like PhoneDisk, etc
Any file system access allows people to change the values in your applications .plist file
Game over.
Now, its not trivial to wrapper that up for the script kiddies but then again its not that hard either.
Storing state in defaults is no more nor less safe from privacy than having two versions of your app. Pirates will either pirate the deluxe version, or they'll pirate the unified version with the flag set.

Do NSUserDefaults persist through an Update to an app in the Appstore?

Is this the case? Do NSUserDefaults get reset when you submit an update to an app on the App Store, or are they reset?
My app is crashing when updated but not crashing when downloaded fully - so I'm trying to determine what could possibly be different in the updated session to the freshly downloaded session.
Cheers,
Nick.
They are usually not reset unless the user deletes the app. For basic data, NSUserDefaults is the best way to save data such as preferences, dates, strings etc. If you are looking to save images and files, the file system is a better bet.
I beleive the answer is YES, it will persist. This also fully documented under the Application Directory chapter in the Apple iPhone OS Programming Guide.
Direct answer to the posted question: YES.
Your problem:
Your app gets crashed due to logic issues. Suppose you store an object in defaults and the app checks it's value on launch (or elsewhere). In you update you could change the way it is checked or used, e.g. you expect a value, but the object is nil, or vice versa. This may cause a SIGABRT or EXC_BAD_ACCESS.
If you had CoreData model and you changed something in your model and update, without managing migration, thats probably reason why your app crashes on update...
I have a similar experience. Our app stores a version number in Settings.Bundle/Root.Plist. This gets displayed through the iPhone Settings app. What we find is that on an Install the version number gets loaded from the app bundle - therefore the version number is correct. On an update however the version number doesn't change. This gives the impression the user is running a previous version of the app. We don't have any logic linked to the version number, it's just for display (it could be used by contact centre staff when diagnosing faults).
Our experience is NSUserDefaults doesn't get cleared when a user updates our app, but the Settings display doesn't get updated either.
Be aware of this case, when your app is running in background and you cannot access your stored values in NSUserDefaults:
Eric:
There have been many threads and bugs about this, but it's happening to me again in ios 9. I have an app that launches in the background in response to NSURLSession tasks and content-available pushes. Reproducibly, if I reboot my phone and wait for a background launch of my app to happen, then when I open the app I find that [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] contains all the system values, e.g. AppleITunesStoreItemKinds, etc. but does not contain any of the values I have set. If I force-quit and relaunch the app all of my values come back. Is there any way to avoid it caching the "empty" standardUserDefaults from before the phone is unlocked, or at least to determine when they are messed up and fix them without having to force-quit the app?
Eskimo (eskimo1#apple.com):
The problem here is that NSUserDefaults is ultimately backed by a file in your app’s container and your app’s container is subject to data protection. If you do nothing special then, on iOS 7 and later, your container uses NSFileProtectionCompleteUntilFirstUserAuthentication, a value that’s inherited by the NSUserDefaults backing store, and so you can’t access it prior to first unlock.
IMO the best way around this is to avoid NSUserDefaults for stuff that you rely on in code paths that can execute in the background. Instead store those settings in your own preferences file, one whose data protection you can explicitly manage (in this case that means ‘set to NSFileProtectionNone’).
There are two problems with NSUserDefaults in a data protection context:
Its a fully abstract API: the presence and location of its backing store is not considered part of that API, so you can’t explicitly manage its data protection.
Note On recent versions of OS X NSUserDefaults is managed by a daemon and folks who try to manipulate its backing store directly have run into problems. It’s easy to imagine the same sort of thing coming to iOS at some point.
Even if changing the data protection were possible, NSUserDefaults has no mechanism to classify data based on the context in which you’re using it; it’s an ‘all or nothing’ API. In your case you don’t want to remove protection from all of your user defaults, just those that you need to access in the background before first unlock.
Finally, if any of this data is truly sensitive, you should put it in the keychain. Notably, the keychain does have the ability to set data protection on an item-by-item basis.
Source:
https://webcache.googleusercontent.com/search?q=cache:sR9eZNHpZtwJ:https://forums.developer.apple.com/thread/15685