简体   繁体   中英

Is it possible that UserDefaults.standard values will not be available to be read?

I know that UserDefaults are meant simply to save preferences, but these preferences are persistent - the values saved in UserDefaults are maintained over an unlimited number of app launches and are always available to be read as long as the app remains installed... right?

Is it possible that these values will be cleared or will not be correctly accessed at any point? After years of using UserDefaults and depending on the consistency of the values they hold, I have now seen twice in one day of work that when my app launched and checked a simple boolean value, the value was not correct.

if defaults.bool(forKey: "beenLaunched") {

This code runs each time the app launches. If the value is true, I do nothing more, but if it is false, I set a few values as this is the user's very first launch of the app and then I call defaults.set(true, forKey: "beenLaunched") and defaults.set(0, forKey: "eventsCompleted") and a few other values.

I found this thread on the Apple forums in which Eskimo said "For the central NSUserDefaults method, -objectForKey:, a result of nil means that the value is unavailable, but there's no way to distinguish between this key is not present and this value can't be fetched because the user defaults are offline." (This appears to be in reference to a specific case of background launching while a device is locked )

I can look into a more secure way of saving simple data such as a Bool value, an Int, or a String, but using UserDefaults for these types of values has always been simple, straightforward, and reliable. Can anybody chime in on the matter and if I was wrong to believe in UserDefaults' persistence?

Thank you!

UserDefaults isn't a "service"; it's never not available to your application. The file it writes to is a PLIST (and therefore all values are stored according to the PLIST standard). For example, all numbers (including booleans) are stored as an NSNumber to the file and can be retrieved either by object(forKey:) or bool(forKey:) . If you use the object method and nothing is set for that value you get nil , whose boolean value is false (or 0 ). Same if you use the boolean method (you get false ). This means no matter which way you go, you'll always get false if there's no value or a value of false . Design your logic around that (which you already have - "beenLaunched" will be empty and therefore false if it's never been launched) and you should be fine.

As for the suggestion of synchronize() , ignore it. Unless you're doing something really weird with threads and preference access or you've interrupted the application immediately after setting a value/object for the problem key, it's got nothing to do with this. Per the very first paragraph of the docs, synchronize() is called periodically as needed. In practice, it's called pretty much immediately after a change occurs.

For context, none of my apps have ever called synchronize() and some of them are old enough to drive. Never a single problem. If you don't have a very good justification for calling synchronize() yourself you almost certainly don't need it and attempts to explain why you do need to sprinkle it everywhere are ... often amusing.

In your specific case, the value stuck by after first run multiple times then suddenly didn't once. Is it possible you changed your app's bundle identifier or name? The defaults are stored by identifier+name so a change would effectively "reset" your app's defaults. Have you been running your app in the simulator and did you just reset-content-and-settings in the simulator? On your device and deleted the app before re-running it on-device?

If you are working in swift then returning nil means objectforkey has not been assigned any value at all . In other case it always returns proper value if you casted saved value properly.

And userdefaults is always available to use, it can never goes offline.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM