Search code examples
iosobjective-cuiviewcontrollersegueupdating

View Controller does not update after receiving data from a segue


iOS Objective-C question: I can't get my View Controller to display values that I've passed in from another View Controller. How can I fix this?

Here's the deal-

I have 4 UILabel properties (planetTitle,planetSubtitle,distanceFromEarth, and distanceFromSun) that behave appropriately whenever I try to change them in the ViewDidLoad method. Example: I tried

planetTitle.text = @"Test"

and it worked fine. However, when I try and change these properties' text values within the method I used to receive the data (called cellWasPressed), it doesn't work. I have tested my cellWasPressed method using breakpoints, and all the data is there just fine- I just simply can't change the property values. It's probably something very basic that I've missed, but please let me know where I'm going wrong. My ViewController.m file is below (kind-of haha). (The updateViews method in there was just to try another approach, which also didn't work).

- (void)viewDidLoad {
   [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
   [super didReceiveMemoryWarning];
}

-(void) cellWasPressed:(Planet *) planet{

   NSString *planetName = planet.planetName;
   NSString *distanceFromSun = [NSString stringWithFormat:@"%.2f Million Miles",planet.distanceFromSun];
   NSString *distanceFromEarth = [NSString stringWithFormat:@"%.2f Million Miles",planet.distanceFromEarth];
   NSString *planetSubtitle = planet.planetDescription;
   [self updateViews:planetName sun:distanceFromSun earth:distanceFromEarth subtitle:planetSubtitle];
}


-(void) updateViews:(NSString *) title sun: (NSString *) sun earth: (NSString *) earth subtitle: (NSString *) subtitle{
   _planetTitle.text = title;
   _planetSubtitle.text = subtitle;
   _distanceFromSun.text = sun;
}

Segue: (I've also added the Planet property to the destination's .h file)

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    PlanetInformationViewController *planetInformationViewController = segue.destinationViewController;

    UITableViewCell *selectedCell = (UITableViewCell *) sender;

    if([selectedCell.textLabel.text isEqualToString:@"Mars"]){
        planetInformationViewController.Planet = _planetList[0];
        [planetInformationViewController cellWasPressed:_planetList[0]];
    }
    else if ([selectedCell.textLabel.text isEqualToString:@"Earth"]){
        planetInformationViewController.Planet = _planetList[1];
        [planetInformationViewController cellWasPressed:_planetList[1]];
    }
    else if ([selectedCell.textLabel.text isEqualToString:@"Jupiter"]){
        planetInformationViewController.Planet = _planetList[2];
        [planetInformationViewController cellWasPressed:_planetList[2]];
    }

}

Solution

  • When you call a method in prepareForSegue which affects outlets it doesn't work because the outlets aren't connected yet at this moment.

    • Create a property in the destination view controller

      @property Planet *planet;
      
    • Assign the planet instance to this property in prepareForSegue

      planetInformationViewController.planet = _planetList[x];
      

      By the way: Find an index based relationship between the planets and _planetList to avoid repetitive code and don't get the name of the planet from the cell (the view). Get it from the data source array (the model).

    • Call [self cellWasPressed] in viewWillAppear and remove the parameter in the method.

      -(void) cellWasPressed {...