I’m using NSUserDefaults to keep an object in sync across several UIViewControllers that are used in a UITabbarController. To do this, I’m implementing the following
- (void)viewWillAppear:(BOOL)animated
{
NSLog(@"ViewControllerX Will Appear");
[super viewWillAppear:animated];
NSDictionary *dict = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"sharedDictionary"];
[customObject setDictionary:dict];
}
- (void)viewWillDisappear:(BOOL)animated
{
NSLog(@"ViewControllerX Will Disappear");
NSDictionary *dict = [customObject dictionary];
[[NSUserDefaults standardUserDefaults] setObject:dict forKey:@"sharedDictionary"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Here customObject is an instance of a custom class that has a property dictionary of type NSDictionary. This object may get changed by the visible UIViewController.
The problem I current have is that when the user switches tabs, say from ViewControllerX to ViewControllerY, these methods aren’t getting called in the expected order. I expect to see this in the log:
ViewControllerX Will Disappear
ViewControllerY Will Appear
but instead I see
ViewControllerY Will Appear
ViewControllerX Will Disappear
The result is that the old dictionary is loaded in ViewControllerY, and only after switching tabs again does the new dictionary appear. Is there an easy way around this problem?
There’s no guarantee which order these methods are going to be called in, so you can’t rely on any ordering with them. The only guarantee you get is that
-viewWillAppear:and-viewWillDisappear:will be called before the view appears or disappears respectively.Another way to deal with this might be changing this to a will/did type scenario. So, you save the current state of your object in
-viewWillDisappear:and you restore the state (i.e., load your dictionary) in-viewDidAppear:. This will guarantee that the view that is going away saves its dictionary before the view that appears.Another approach would be to change the way the custom dictionary is passed between your view controllers and use a delegate object on your application’s
UITabBarViewControllerto deal with syncing these changes to the user defaults. You can integrate this into your app however makes the most sense, but I’ll provide a basic example below along with the changes you’d need to provide to your app (as described in your question):To use the example, you need to make these changes (adapt to your coding style):
NSDictionaryto ivar named_sharedDictionaryto your application delegateUITabBarControllerDelegateprotocolUITabBarController.sharedDictionary-viewWillAppearyou set the value of the view controller’ssharedDictionaryproperty to your custom object and just continue as you did beforeAfter you’ve done those things, add the following method implementation to your app delegate: