views:

51

answers:

5

How do I refer to the preceding view controller's properties and iboutlets in a uinavigationcontroller stack of views?

For instance, say the first screen has a high score uilabel, and the second screen is the game. How would I update this label from the game screen before popping back to it?


EDIT

Thanks for the answers. I think I will use Key Value Observing to change a Singleton classes highScore method. This blog post was useful in understanding how to do this: http://www.bit-101.com/blog/?p=1969

+1  A: 

You could do one of the following things:

  • use the 'viewcontrollers' property of your UINavigationController object (answer to your question, but not really the best solution)
  • set up a delegate method that calls an update method on the first viewController from the second one
  • use notifications (recommend, as you then could update the score wherever needed)
RupertP
A: 

you say you are using UINavigationController, so a simple (and needed to be expanded on) way to do this could start with (assuming you are in the current view controller:

//gets the number of items on the navigationController stack
int arrayCount = [[[self navigationController] viewControllers] count];

//assumes you know where this view controller is on the stack in relation with the current VC (in this code example, it is the one directly below the top (hence the -1)) (tricky on occasion)
lastViewController = [[[self navigationController] viewControllers] objectAtIndex:arrayCount-1]
Jesse Naugher
+1  A: 

The cleanest way to pass information is to use the NSNotifcationCenter service. The quickest way is to add a reference to the viewController's parent.

in game.h:

UIViewController *parentController;   

@property (nonatomic, retain) UIViewController *parentController;

in screen.m // before displaying the game view: self.gameController.parentController = self;

in game.m

parentController.highScore = highScore;
// dismiss the game viewController

The cleaner way is to use NSNotificationCenter. Though it seems complex, once you do it once I think you'll find it clean and easy.

Here's a nice explanation.

joelm
+1  A: 

You could use Key-Value Observing on a property of some object. Say you pass an Object to a view controller that you push on your navigation controller called PlayerState. The first view controller could observe this property

[PlayerState addObserver:self forKeyPath:@"highScore" options:NSKeyValueObservingOptionNew context:nil]

Then every time the high score object changes you will get notified by implementing following function

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

This method improves upon several of the other methods because it decouples the implementation of the placement of your view controllers and the game logic. You might change where the high score is displayed, but you always want it to be changed if the underlying object changes. Notifications is a very similar way of doing this but requires you to post a notification each time you change the high score object. KVO will do this automatically.

DHamrick
+1  A: 

Think about the data.

The "high score" is global to your app (for a specific game type, but we'll assume there's only one game type). If there's another view that shows the high score (e.g. "game over, you failed to beat the high score"), it refers to the same score, not another.

In this case, store the score in the app delegate (which is, for most purposes, "global"); you can get it with something like MyAppDelegate * appDelegate = (MyAppDelegate*)[[UIApplication sharedApplication] delegate]; .

Alternatively, pass a "context" around; in this case, maybe a HighScore* or something, and store the score in the object. This makes it easier to extend to multiple game types later.

Then use NSNotificationCenter to pass "high score changed" notifications around. Alternatively, use KVO on the high score's value (I've never used it though).

tc.