views:

53

answers:

3

Hello, I am trying to solve a problem considering update of an view. First I switch to another view by using:

- (void)viewSettings {
 settingsViewController = [[SettingsViewController alloc] initWithNibName:nil bundle:nil];
 [[self viewController] presentModalViewController:settingsViewController animated:YES];}

Which is a delegate Method called by

ivaskAppDelegate *mainDelegate = (ivaskAppDelegate *)[[UIApplication sharedApplication] delegate];
 [mainDelegate viewSettings];

I switch back by calling another dellegate method

- (void)settingsDone {
 [[self viewController] dismissModalViewControllerAnimated:YES];}

When I return to my view I now want to update a label, can you explain how to do it?

I use NIB-files which have a controller class and a view class connected in the identity inspector.

/N

+1  A: 

You will need to set up a delegate that is implemented in your main view controller (where you need to have the label updated), and that is called from your settings view controller. I have a blog post that describes how to do this:

http://www.dosomethinghere.com/2009/07/18/setting-up-a-delegate-in-the-iphone-sdk/

BP
A: 

You would make your view controller conform to a protocol that your create. In this case it may be named SettingsDelegate. That protocol contains one message - (void)didFinishSettingsWithSomeNewValue:(id)newValue;

The Settings Controller has a delegate instance variable and a property of type id<SettingsDelegate>

Before you present the settings viewController you assign the parent view controller to the delegate property. In the settings view controller you send a didFinishSettingsWithSomeNewValue: message to your delegate (the parent view controller) along with some new value. The parent view controller implements that method and inside the implementation can dissmiss the modal controller and update any views on itself.

tonklon
I used - (void)willMoveToSuperview:(UIView *)newSuperview { ivaskAppDelegate *mainDelegate = (ivaskAppDelegate *)[[UIApplication sharedApplication] delegate]; productLabel.text = mainDelegate.product;}in my view and It seem to work. Is this totally wrong?
Nicke
Well, I do not know your app and your specific needs, but generally spoken: YES, this is totally wrong!! You are working against Cocoa's underlying design patterns. This may work well one single time, but as your app grows your code will definitely become an unreadable mess. See my other answers for more options.
tonklon
+1  A: 

Although I heavily suggest delegation in this case there are two other options, that come to my mind: Notification and KVO.

Notification

Whenever settings are changed the settings view controller could post a Notification, to let other parts of the app know about this change. Posting a notification is easy as:

[[NSNotificationCenter defaultCenter]
      postNotificationName:@"SettingsChangedNotification" object:theNewSettings];

Every object that somehow want to know about a settings change can subscribe to that notification via:

//Subscribe (in viewDidLoad or init)
[[NSNotificationCenter defaultCenter]
          addObserver:self selector:@selector(settingsChanged:)
          name:@"SettingsChangedNotification" object:nil];

// Called when a "SettingsChangedNotification" is posted
- (void)settingsChanged:(NSNotification*)settingsChangedNotification {
    id newSettings = [settingsChangedNotification object];
}

//Unsubscribe (in viewDidUnload or dealloc)
[[NSNotificationCenter defaultCenter]
          removeObserver:self name:@"SettingsChangedNotification" object:nil];

See Notification Programming Topics

If you are trying to manages UserDefaults with your settingsViewController there's an even better way. Just set the values on the sharedUserDefaults and the app will post a NSUserDefaultsDidChangeNotification notification all on it's own. All objects that depend on user settings could subscribe to that notification, and after it's posted reread the userDefaults.

See

Key-Value Observing (KVO)

Your rootViewController could observe changes of an object, which it needs to synchronize with, by Key-Value Observing.

One object registers itself as observer for keyPaths on other objects by sending them a addObserver:forKeyPath:options:context: message. The object is informed about changes via the observeValueForKeyPath:ofObject:change:context: callback method. KVO could sometimes be difficult the get right, because you have to ensure, that you register and unregister the same number of times, before an object gets deallocated.

See Key-Value Observing Programming Guide

Conclusion

Please refrain from using "global" variables on your app-delegate. There's enough possibilities to do better. The sooner you dive into them, the better code you will write.

tonklon
This was really helpful. Thank you very much. I start to wonder if my class structure are totaly wrong.I have a classnameViewController, a classnameView but also a NIB file. Is it a correct way to build my app? or should I just use the controller class and a NIB? I have some apps in appStore that is non complex and it works just fine to build these apps like this. But when thinking about bigger projects I think that getting the structure right is vital. Maybe I struggle so much understanding the MVC structure because I use NIBs instead of doing everything programatically?..
Nicke
@Nicke Welcome on Stack Overflow. If an answer was helpful vote it up using the arrow above the number in the left top corner of the answer. If it is bad, wrong or didn't answer the question downvote it. If an answer solved your question mark it as accepted. If new questions arise, that are only remotely related to the original question ask them using the "Ask question" button on the top of the page. Read the FAQ beside the search box. If questions arise about the usage of the site check meta.stackoverlow.com
tonklon