Michael
Michael

Reputation: 31

How to change a UILabel one one View Controller from another View Controller?

I am relatively new to Xcode and have tried to find the answer by searching, without luck.

My app has 5 View Controllers, V1 through V5, which are embedded in one Tab Bar Controller. Each View Controller has a segue to one and the same Setup Menu View Controller. The Menu changes some labels on the View Controllers. I use a delegate to make sure that the View Controller that calls the Menu gets updated with the new settings when you leave the Menu. However, this allows me to modify only the labels on the View Controller that called the Menu Controller, not on the 4 other ones.

I work form a Story Board. Is there a simple way to set the UILabels on V2, V3, V4 and V5 from V1 (and vice versa), or even better, set the labels on V1 through V5 from the Menu View Controller (which is not embedded in the Tab Bar Controller)?

I have seen something that could help here, but this seems rather complicated for what I want. The label changes I need are quite simple and are all predefined. Is there a method that is called every time you switch tabs in a tabbed application? Similar to ViewDidLoad?

Upvotes: 1

Views: 2615

Answers (4)

Michael
Michael

Reputation: 31

Thanks a lot guys, I am impressed by your quick responses. In this particular case, viewWillAppear does the trick:

- (void)viewWillAppear:(BOOL)animated
{   [self AdaptLabels]; 
    NSLog(@"View will appear.");
}

Every time a new tab is chosen, it updates the labels in the new View, according to a global variable set by the Menu, just before they appear. Very quick and clean. Thanks to all of you!

Upvotes: 0

dfmuir
dfmuir

Reputation: 2088

This sounds like a good time for NSNotificationCenter. You are going to have your MenuViewController generate a notification with the new data that should be updated in your other view controllers:

// User has updated Menu values
[[NSNotificationCenter defaultCenter] postNotificationName:@"MenuDataDidChangeStuffForLabels" object:self userInfo:@{@"newLabelValue" : labelText}];

In your V1, V2, etc. you can add subscribe to these notifications using this code in your viewDidLoad method:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Subscribe to NSNotifications named "MenuDataDidChangeStuffForLabels"
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateLabelText) name:@"MenuDataDidChangeStuffForLabels" object:nil];
}

Any object that subscribes using that code will call the updateLabelText method anytime a notification with that name is posted by the MenuViewController. From that method you can get the new label value and assign it to your label.

- (void)updateLabelText:(NSNotification *)notification {
    NSString *newText = notification.userInfo[@"newLabelValue"];
    myLabel.text = newText;
}

Upvotes: 3

rdurand
rdurand

Reputation: 7410

Here is a very simple solution if your workflow is also simple. This method changes all the labels from the different ViewControllers directly from what you call the Menu ViewController.

Let's say you have the following situation :

Storyboard

The blue ViewController is of the FirstViewController class. The green ViewController is of the SecondViewController class. The labels on each of those are referenced by the properties firstVCLabel and secondVCLabel (on the appropriate class' header file). Both these ViewControllers have a "Modal" button which simply segues modally on touch up inside.

So when you clic on any of these two buttons, the orange ViewController (of ModalViewController class) is presented. This ViewController has two buttons, "Change Label" and "Back", which are linked to touch up inside IBActions called changeLabel: and back:.

Here is the code for the ModalViewController :

#import "ModalViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"

@interface ModalViewController ()

@end

@implementation ModalViewController

// Action linked to the "Change Label" button
- (IBAction)changeLabel:(id)sender {

    // Access the presenting ViewController, which is directly the TabBarController in this particular case
    // The cast is simply to get rid of the warning
    UITabBarController *tabBarController = (UITabBarController*)self.presentingViewController;

    // Go through all the ViewControllers presented by the TabBarController
    for (UIViewController *viewController in tabBarController.viewControllers) {

        // You can handle each ViewController separately by looking at its class

        if ([viewController isKindOfClass:[FirstViewController class]]) {

            // Cast the ViewController to access its properties
            FirstViewController *firstVC = (FirstViewController*)viewController;
            // Update the label
            firstVC.firstVCLabel.text = @"Updated first VC label from Modal";

        } else if ([viewController isKindOfClass:[SecondViewController class]]) {

            SecondViewController *secondVC = (SecondViewController*)viewController;
            secondVC.secondVCLabel.text = @"Updated second VC label from Modal";
        }
    }
}

// Action linked to the "Back" button
- (IBAction)back:(id)sender {

    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}

For the sake of completeness, here are FirstViewController.h :

#import <UIKit/UIKit.h>

@interface FirstViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *firstVCLabel;

@end

And SecondViewController.h :

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *secondVCLabel;

@end

There is no relevant code in the implementation of these classes.

Upvotes: 0

Aaron Wojnowski
Aaron Wojnowski

Reputation: 6480

What I would do is subclass the tab bar controller and set that as the delegate for the menu view controller. From there, you can get updated when the labels are supposed to change and then communicate with the 5 tabs and update the labels.

Alternatively, you could use NSNotifications to let all the 5 view controllers know when settings change.

Lastly, you could add the menu settings to a singleton and have all of the view controllers observe the various properties that can change.

The label changes I need are quite simple and are all predefined. Is there a method that is called every time you switch tabs in a tabbed application? Similar to ViewDidLoad?

Regarding this question, the methods you're looking for are viewWillAppear: and viewDidAppear.

Upvotes: 0

Related Questions