Is it bad form to synchronize NSUserDefaults in -(void)dealloc?
Asked Answered
V

2

7

I load from NSUserDefaults in my object's init method. Can I save to NSUserDefaults in my object's dealloc method?

Something exactly like:

-(void)dealloc {
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setObject:self.filenamesArray forKey:self.defaultsKey];
    [userDefaults synchronize];
    self.filenamesArray = nil;
    self.defaultsKey = nil;
    [super dealloc];
}

good, bad, ok? if it's not good, where would be better.

Edit:

Thanks for the detailed responses. All those things make sense. Another reason I discovered why this is a bad place to save to user defaults, is that dealloc is only called when an object deallocates nicely. If my app is killed, this code never runs. Similarly, if the app is pushed into the background (iOS 4) this doesn't run. I've also removed the explicit [userDefaults synchronize] call. It makes me a little nervous, but I put my trust in apple on this one. :)

Vinegarroon answered 13/11, 2010 at 22:48 Comment(0)
C
7

It's bad because by the time -dealloc is called, other objects have given up interest in it. This can have lots of different implications.

The better place to set user defaults is the very moment a setting changes. That way it's persisted right away and the app can be killed with no worries about a setting not being persisted because parts of your object graph might already have gone away.

Crider answered 13/11, 2010 at 22:58 Comment(0)
P
0

Synchronizing the user defaults in -dealloc is no different than anywhere else. This is because, crazy though it may seem, -dealloc is not in any way magical, and unlike, say, C++ destructors, -dealloc is actually exactly a typical method. You could be slightly more worried about passing self.filenamesArray to userDefualts, because thats actually something that may be held past the actual deallocation, but I trust that the user defaults retains it.

As to when you should [userDefaults synchronize];, people vary, and I personally disagree with @Joshua -- I never explicitly -synchronize, but rather let NSUserDefaults take care of it. Unless I am very much mistaken, it fires automatically when the app closes, as well as periodically otherwise. As it knows when it has been updated, and it needs to write the entire plist file at once, I think that I would rather let Apple's algos handle when its time to write the defaults, since it is takes non-trivial time (because it writes to the file system).

(Note that none of the last paragraph applies if you have special circumstances surrounding your user defaults, such as another application reading/writing them)

Peru answered 13/11, 2010 at 23:26 Comment(3)
I agree with Jared, synchronize should only be used to "force" syncing. This can be useful for example when debugging and there's a chance of crashing, etc.Affaire
I don't recall anyone presenting -dealloc as "magical". The point is that it's generally bad practice specifically because this part of your object graph is being torn down. Doing anything other than tear-down (such as removing self from a notification center, etc.) creates one more area of your application that could misbehave as your class becomes more complex. Especially when you consider weak references to other objects that may already have gone bye-bye by the time this object's -dealloc is called. The code as it is now looks harmless but that could easily change.Crider
The above said (ran out of room), I agree that the call to -synchronize is unnecessary, however setting the user defaults is what I mainly have the issue with. The OP is not just calling synchronize, he's waiting to set the defaults during a -dealloc call. I've changed the wording of my original answer to reflect this distinction.Crider

© 2022 - 2024 — McMap. All rights reserved.