3

I have one view controller named FirstViewController, and a second named SecondViewController. I present second view controller with

 UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"mainController"];
[self presentViewController:controller animated:YES completion:nil];

In SecondViewController's .m, I want to change the text of a UILabel in FirstViewController. However, the label's text isn't updating. How would I make it so that the FirstViewController's label is updated when a UIButton is pressed in SecondViewController?

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
user1626438
  • 133
  • 5
  • 14
  • 1
    Try a delegate pattern: http://stackoverflow.com/questions/626898/how-do-i-create-delegates-in-objective-c Or using notifications: http://stackoverflow.com/questions/2191594/send-and-receive-messages-through-nsnotificationcenter-in-objective-c/2191802#2191802 – Nicholas Hart Aug 12 '13 at 18:59

4 Answers4

6

You could use the delegate pattern

First create your delegate protocol

@class SecondViewController;

@protocol SecondViewControllerDelegate

-(void) updateLabelWithString:(NSString*)string

@end

@property (weak, nonatomic) id<SecondViewControllerDelegate>delegate;

In your IBAction connected to your UIButton

[self.delegate updateLabelWithString:yourString];

in FirstViewController.h

#import "SecondViewController.h"

@interface FirstViewController : UIViewController <SecondViewControllerDelegate>

in FirstViewController.m

-(void) updateLabelWithString:(NSString*)string {
   label.text = string;
} 

then when you create your controller instance, set FirstViewController as the delegate for your mainViewController

controller.delegate = self;
Chris Tetreault
  • 1,973
  • 13
  • 19
  • 1
    Upvoted this answer so that OP can learn more about the delegate pattern. One of the toughest things to understand for me, as a new dev, was the delegate pattern. I don't think that this is the "best" solution but it's worth learning about. It makes properties and references make a lot more sense later on. – Daddy Aug 12 '13 at 19:11
  • 1
    I agree with Justin on everything. Good to learn, but not a pattern to use for passing values between view controllers. A good example for delegation is loading of data into a tableview. Delegation is when you want something to happen outside of your veiw controller and for your current active view controller to be updated upon completion or activation (active touches on screen). Which is different than passing values from one view controller to another. – Ben Coffman Aug 12 '13 at 19:14
  • 1
    @JustinAmberson and BenCoffman, thanks for the input, for some reason delegation is always my first instinct when it comes to passing values back, especially since it was one of the first things I learned. Hopefully OP will take time to consider all options suggested in this thread though – Chris Tetreault Aug 12 '13 at 19:20
4

There are other answers here that are good. I posted this up so I could be sure that you'd see it. I have left comments on other answers here that you may not see.

There are a few ways to go about implementing your solution.

  1. KVO (Key Value Observing)

    KVO is a way to "observe" the state of any object, and get notified when that object changes. KVO can be tough to learn as a new dev. Think of it like this. If you know that x = 1, and you want to know if x ever changes, you can set up to "observe" x. If x ever gets changed, an event happens and your "observing class" will be notified that a change has occurred, and what the scope of the change was. I will sometimes monitor the count of a mutable array to see if items have been added or removed.

  2. NSNotification

    NSNotification is similar to KVO, except there is nothing automatic about it. Like KVO, you set up an "observer" class, and listen for a specific "event" to happen. You choose when the event happens, and you create an NSNotification and "post" it. Any class that is listening as an "observer" will see that notification and take action if appropriate.

  3. Delegate pattern

    This is an answer from above. It's important to learn how delegation works. For your exact situation I don't think it's the correct course of action, but it WILL work. You need delegation because of "encapsulation", which means that Class A should not have any clue what is going on in Class B, and vice versa. Using delegation encourages independence among classes.

  4. Singleton/SharedInstance

    I believe this is the best way to handle your current issue. But, it's not the end all/be all. Singletons help enforce "MVC" (model, view, controller) pattern programming. It's part of the encapsulation thing. The "model" stores information. The "view" shows the information. The "controller" connects the model to the view. In this case, both your first and second views are part of the "V" convention of MVC. The "M" would be your singleton class. The "C" would be your viewControllers, accessing the singleton and displaying the value.

Sorry for not spelling out how to do each one. All four are tutorials in themselves. Just want you to go forth with new understanding.

EDIT: I want to point out that I use singletons like a portable database. Usually setup with helper methods, like quickly finding the libraryPath, encoding to NSData, so as not to clutter up the appDelegate. There will usually be one master array object that stores information needed in several classes. Maybe the array has a bunch of NSDictionaries representing items in an online storefront. I don't mean for him to start storing dataModel.classALabelText = @"Hello World"; in it, but it's a good jumping off point

Daddy
  • 9,045
  • 7
  • 69
  • 98
  • A volatile portable database. It goes away when the app is closed. – Ben Coffman Aug 12 '13 at 19:54
  • Right, which is why I implement my archiving methods in it :-) – Daddy Aug 12 '13 at 20:03
  • I think you're on the right track. I used to use delegates willy nilly for all sorts of stuff, without completely understanding it – Daddy Aug 12 '13 at 21:08
  • Thank you for taking the time to write such a detailed answer. I think I'll use delegation because it seems to be the easiest to understand. Thanks again for the answer, and Ill definitely look into the other methods for future use – user1626438 Aug 12 '13 at 22:18
  • I'm thinking about trying to write a down to earth blog post covering some of this stuff, i'll let you know if i do – Daddy Aug 12 '13 at 22:43
3

If you follow the Model-View-Controller paradigm (or architecture), then you should change the value in the model (i.e., in the object that implements your model). The controller layer should then make sure that all relevant views are updated in the UI.

That way you don't have to have view controllers propagate updates between them.

Monolo
  • 18,205
  • 17
  • 69
  • 103
2

One of the most common ways to do this is to create a sharedInstance class where you can store the value no matter what controller you are in and then read from it when the controller you want is displayed.

A good example:

Question regarding SharedInstance

A decent tutorial here:

http://iphonedevsdk.com/forum/iphone-sdk-tutorials/24135-singleton-classes.html

You can also use

prepareForSegue:sender:

And there are plenty of examples on Stackoverflow for this.

Community
  • 1
  • 1
Ben Coffman
  • 1,750
  • 1
  • 18
  • 26
  • There are better patterns to use than singletons. eg: delegation, notifications, KVO... – Nicholas Hart Aug 12 '13 at 18:57
  • These are all other options. Not necessarily better. I'm referring to the most common practice from what I have seen. I would argue KVO is unquestionably not better, but again this is a debate. Down voting for this is not cool. Plus why would you use delegation and tightly couple the two classes, that would be bad. I strongly disagree with your statement. – Ben Coffman Aug 12 '13 at 19:03
  • I upvoted you back to 0. I use singleton classes all the time and would agree with your answer. Maybe the downvote was because your answer was just some links. Maybe you could have spelled out that you update the singleton in one class, and the other class monitors for changes inside with NSNotification, KVO, or using the viewWill... methods of UIViewController – Daddy Aug 12 '13 at 19:09
  • I downvoted because most of the time using a singleton pattern is the wrong approach--and talk about tight coupling! Not only do you have an interface you're writing to, you've only got a single instance as well! – Nicholas Hart Aug 12 '13 at 20:21
  • Let me explain tight coupling. With a delegate you have to have the delegate methods declared in your class you are assigning the delegate to. With SharedInstance, I don't have to update anything, no warning, no errors, if I don't update and or retrieve data, therefore, it's not tightly coupled. This may help align our thoughts. – Ben Coffman Aug 12 '13 at 20:28