0

My app has an UITabViewController with 3 tabs. The first two tabs will read some data from disk and display it (done in viewDidLoad of the first two tabs).

The third tab has some kind of config information. If the user changes the config information in the third tab, i want the first two tabs to be refreshed, i.e., viewDidLoad should be re-called.

I cannot use viewWillAppear in the first two tabs, as the read from disk part is kind of intensive and I wouldn't want to do it everytime the tab is clicked. Also, I need to do some auxiliary tasks (in addition to updating the first two tabs) when the third tab data is edited, so I want to reload the tabs via viewDidLoad, while doing those auxiliary tasks.

Sankar
  • 6,192
  • 12
  • 65
  • 89

3 Answers3

3

Use NSNotifications to do this.

Since the third tab is your config settings you will probability want to be storing these in NSUserDefaults so use the NSUserDefaultsDidChangeNotification to watch for this in your viewDidLoad method and move your reloadData code into its own method.

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self
                           selector:@selector(userDefaultsChanged:)  
                               name:NSUserDefaultsDidChangeNotification
                             object:nil];

    [self reloadData];
}

Now this will trigger a call to the method userDefaultsChanged: whenever your defaults are changed, add the method as follows.

- (void)userDefaultsChanged:(NSNotification *)notification
{
    [self reloadData];
}

- (void)viewDidUnload
{
    [super viewDidUnLoad];

    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Edit: Alternative method to watch for specific default values

[[NSUserDefaults standardUserDefaults] addObserver:self
                                        forKeyPath:@"SomeDefaultKey"
                                           options:NSKeyValueObservingOptionNew
                                           context:NULL];

- (void)observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context
{
    if([keyPath isEqual:@"SomeDefaultKey"])
    {
       // Do Something
    }
    if([keyPath isEqual:@"SomeOtherKey"])
    {
       // Do Something else
    }
}
trapper
  • 11,716
  • 7
  • 38
  • 82
  • Thanks. I got the notification fired correctly. But how do I filter and find out which key changed in the userdefaults ? I googled but could not find much docs related to this on iOS. I got only some Mac OS links and it was not helpful really. – Sankar May 28 '12 at 11:12
  • If you need to know when a specific default has changed then you should use the `addObserver:forKeyPath:options:context:` method instead to watch that specific value. And then implement the method `observeValueForKeyPath:ofObject:change:context:` to process this. – trapper May 28 '12 at 11:30
  • if we have registered for "SomeDefaultKey" why will the observeValueForKeyPath be called at all for "SomeOtherKey" too ? Either way, when I tried the above code, the observerValueForKeyPath was not called at all :( – Sankar May 28 '12 at 11:58
  • You could register for multiple keys so `SomeOtherKey` just there as an example how you would distinguish between them in the method. I think you should post a new question about watching specific NSUserDefaults keys & post your not working code there and we can help fix. – trapper May 28 '12 at 12:02
  • Yes, I think that is a better thing to do. Thanks. http://stackoverflow.com/questions/10784439/ios-nsuserdefaults-watching-the-change-of-values-for-a-single-key is the new question. – Sankar May 28 '12 at 12:09
1

You can use the -(void)viewWillAppear:(BOOL)animated method to trigger the refresh on the other two view controllers.

If you don't want to reload the data every time the user clicks the Tab you may use NSNotifications to trigger a refresh. See a detailed explanation at: http://www.numbergrinder.com/2008/12/patterns-in-objective-c-observer-pattern/

rene
  • 41,474
  • 78
  • 114
  • 152
1

I would use -(void)viewWillAppear:(BOOL)animated. To get around the read from disk being 'kind of intensive' you could set a flag when the config changes in the 3rd tab and then only read from disk in the other tabs if that flag is set

Josh
  • 3,445
  • 5
  • 37
  • 55
  • Yes, I could do that. I almost started it. But wanted to know if there is some other way to trigger viewDidLoad instead of adding such flags. – Sankar May 28 '12 at 10:10
  • 1
    Of course it'd be possible to call the method `viewDidLoad`, the same as you'd call any other method. But that would mean that each tab controller would need to know about the other tabs which starts getting needlessly complicated. You'd want to investigate using a delegate, but that's what `viewWillAppear` is there for. – Josh May 28 '12 at 10:22
  • Calling viewDidLoad manually would be very bad. You should never do this. – ader May 28 '12 at 10:26