Synchronizing plist across a Tab Bar Application

大兔子大兔子 提交于 2019-12-11 05:47:47

问题


I have a three tab application that shares a plist for connection information (Client ID, Server Address, Port Number). In each of the view controllers, an NSUserDefaults object is initialized within the viewDidLoad method:

- (void)viewDidLoad {
    [super viewDidLoad];

    // load default settings into class instance variables
    defaults = [NSUserDefaults standardUserDefaults];
    self.clientID = [defaults objectForKey:@"clientID"];
    self.serverAddress = [defaults objectForKey:@"serverAddress"];
    self.serverPort = [defaults objectForKey:@"serverPort"];
}

One of my views represents a "Settings" page that allows a user to make changes to the plist. However, when the plist is updated, the changes aren't reflected across all of the tab views because a synchronize is needed for each of the objects:

[defaults synchronize];

I've learned that the viewDidLoad method is only called once during the lifetime of an application (at least for a Tab Bar application), so, I can't put the synchronize calls here. I then turned to the AppDelegate class and discovered the tabBarController method. How do I use this method to synchronize the NSUserDefaults objects across all view controllers without the need for a sync button? Is this even the correct way of sharing/adjusting preferences while an application is open?

Here's where I'm at now:

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {

    // I need to synchronize somewhere in here???
    switch (tabBarController.selectedIndex)
    {
    case 0:
        NSLog(@"Tab 0 selected");
        break;
    case 1:
        NSLog(@"Tab 1 selected");
        break;
    case 2:
        NSLog(@"Tab 2 Selected");
        break;
    }
}

Thanks ahead of time.


回答1:


Try syncing the defaults in viewWillAppear instead of viewDidLoad.

It may happen that viewDidLoad is called multiple times (in which case, viewDidUnload will have been called between), for example, if there is a memory issue.

By synchronizing the defaults in viewWillAppear, you are ensuring that the relevant UIViewController is updated just before it becomes the selected view controller.




回答2:


Rather than force a lot of extra loads by re-syncing on every view display, you can have each of your view controllers register as a notification observer when they get loaded (viewDidLoad), and whereever you change your settings, you post a "settings_changed" notification. (This is an incredibly useful pattern for decoupling objects that need to communicate).

So each of your viewDidLoad methods will have this:

  [[NSNotificationCenter defaultCenter] 
        addObserver:self 
           selector:@selector(refreshDefaults) 
               name:@"Defaults_changed" 
             object:nil];

The viewDidUnload will unregister the vc:

  [[NSNotificationCenter defaultCenter]
        removeObserver: self 
                  name: @"Defaults_changed"
                object: nil];

Handle the event:

 - (void) refreshDefaults {
   // re-load your defaults here
 }

Any place that makes a change will do this:

  [[NSNotificationCenter defaultCenter] 
     postNotificationName:@"Defaults_changed"
                   object: nil];



回答3:


You only need to call synchronize when you've made changes. Every time you call setObject:obj forKey:@"key" to set the object, call synchronize directly afterwards.

Also, instead of creating a pointer to NSUserDefaults try using the shared instance directly, like [[NSUserDefaults standardUserDefaults] objectForKey:@""]; and [[NSUserDefaults standardUserDefaults] setObject:obj forKey:@""]; to set the objects. Then call synchronize after setting an object.



来源:https://stackoverflow.com/questions/6631442/synchronizing-plist-across-a-tab-bar-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!