ScottMcGready
ScottMcGready

Reputation: 1622

Using "self" in externally called method

I have a main View Controller (ViewControllerA) which has a container with a child View Controller (ViewControllerB) inside with a few labels and buttons. During the app's usage, NSUserDefaults will change and the labels in ViewControllerB need to be updated (simplified version).

I've got a method inside the ViewControllerB's class file which I can access from ViewControllerA however calling the method does not update the labels which I suspect is due to the self reference. The method definitely fires and I've included ViewControllerB's class in the header of ViewControllerA etc.

- (void)testingMethod{        
    if(![[NSUserDefaults standardUserDefaults] stringForKey:@"firstValue"]){
        [[NSUserDefaults standardUserDefaults] setObject:@"0" forKey:@"firstValue"];
        [[NSUserDefaults standardUserDefaults] setObject:@"0" forKey:@"secondValue"];
        [[NSUserDefaults standardUserDefaults] setObject:@"Never" forKey:@"thirdValue"];
    }
    self.firstLabel.text = [[NSUserDefaults standardUserDefaults] stringForKey:@"firstValue"];
    self.secondLabel.text = [[NSUserDefaults standardUserDefaults] stringForKey:@"secondValue"];
    self.thirdLabel.text = [[NSUserDefaults standardUserDefaults] stringForKey:@"thirdValue"];
}

The method is called from an IBAction from within ViewControllerA's class like so:

- (IBAction)doThis:(id)sender{
    ViewControllerB * something;
    something = [[ViewControllerB alloc] init];
    [something testingMethod];
}

My question then is how can I get those labels to change when calling that method from outside the class it was created in?

Interface builder example screenshot: enter image description here When the button is clicked, the label in the child view should update.

Upvotes: 0

Views: 99

Answers (2)

streem
streem

Reputation: 9144

You don't call the testingMethod on the same instance than the one displayed. You need to have an ivar declared in your ViewController A, then you would have something like this

In ViewController A.h

@class ViewControllerB;

@interface ViewControllerA : UIViewController
{
    ViewControllerB *viewControllerB;
}

In ViewController A.m

//Add this method to get the viewControllerB instance
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    //This identifier is set in the storyboard, in the attribute inspector of the segue
    if([[segue identifier] isEqualToString:@"segueVCB"])
    {
        viewControllerB = [segue destinationViewController];
    }
}

- (IBAction)doThis:(id)sender{
    [viewControllerB testingMethod];
}

Basically, imagine your viewControllerA is your car and viewControllerB is your headlights. You want to turn on the headlights by clicking a button. You added correctly the headlights to your car, but when you click the button you create another headlight that is never added and you expect the one on your car to lights on. That does not make any sense. You need to have one pair of headlights and to activate those when you click the button.

Upvotes: 1

Fogmeister
Fogmeister

Reputation: 77641

Can you try using objectForKey instead of stringForKey.

I don't think (not 100%) that they're interchangeable in the way you are using them.

EDIT

OK, the way you're accessing ViewControllerB is not correct. You are creating a completely fresh instance of it.

You might have ViewControllerB as a subview/child view controller but that isn't what you're running the method on.

You need to get the child view controller and run the method on that. @Justafinger was quicker than me. Do what he said.

Upvotes: 0

Related Questions