1

When I try to call the getter methods "gender" and "teamName" from another class (by creating an instance of the TeamsViewController class and calling the methods on that instance), the methods return null. Why is this?

Thanks for your help.

@interface TeamsViewController () {
    NSString *teamName;
    NSString *gender;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    gender = @"boys";
    teamName = @"Basketball";
}

-(NSString *)gender {
    NSLog(@"returning %@",gender);
    return gender;
}
-(NSString *)teamName {
    NSLog(@"returning %@",teamName);
    return teamName;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (onBoys==true) {
        gender = @"boys";
    }
    else {
       gender = @"girls";
    }

    [self performSegueWithIdentifier:@"teamsPushSegue" sender:self];
}



TeamsViewController *teamsInstance = [[TeamsViewController alloc]init];     
[teamsInstance gender];
Rob
  • 415,655
  • 72
  • 787
  • 1,044
JordanD
  • 163
  • 6
  • 1
    Show the code from the other class where you create the instance and call the methods. – rdelmar Dec 23 '13 at 17:31
  • TeamsViewController *teamsInstance = [[TeamsViewController alloc]init]; [teamsInstance gender]; – JordanD Dec 23 '13 at 17:32
  • 1
    Most likely because those ivars are still `nil`. `-viewDidLoad` will be called when needed, if you haven't done anything which causes that controller's view to be loaded and ask for those values before they have been initialized then they will be nil. – Jonah Dec 23 '13 at 17:35

2 Answers2

5

Creating an instance of the class with:

TeamsViewController *teamsInstance = [[TeamsViewController alloc] init];

Won't call the method viewDidLoad where those instance variables are initialised.

Instead initialise them in an init method:

- (id)init {
    self = [super init];
    if (self) {
        gender = @"boys"; 
        teamName = @"Basketball";
    }
    return self;
}

However the method you probably want to override is initWithNibName:bundle: and you probably want to avoid calling the init method at all.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • Thanks! However, I have a TableView in TeamsViewController, and I change the values of gender when a cell is selected. I am trying to access the values of the current instance - the one made with viewDidLoad. Maybe the best way isn't to create a new instance? – JordanD Dec 23 '13 at 17:40
  • @trojanfoe Agreed, or if using storyboards, override `initWithCoder`. – Rob Dec 23 '13 at 17:40
  • 1
    @JordanD Absolutely you do not want to create a new instance. You want to retrieve reference to existing instance. – Rob Dec 23 '13 at 17:41
  • How do I do that? Sorry for the "bad" questions, it's just that I am pretty new to iOS development. – JordanD Dec 23 '13 at 17:43
  • @JordanD Assuming you're trying to access this from a different view controller, you should see [Passing Data between View Controllers](http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers). As rdelmar suggested, you should probably clarify your question to describe a bit more about what this "other" class is, the relationship to this view controller, etc. – Rob Dec 23 '13 at 17:46
  • Thanks SO much! I'm trying to make a sports app for my high school, and I really appreciate your help. – JordanD Dec 23 '13 at 17:53
4

By the way, you might want to avail yourself of public properties, rather than explicitly defining instance variables and getter methods yourself. For example:

TeamsViewController.h:

@interface TeamsViewController : UIViewController

@property (nonatomic, copy) NSString *teamName;
@property (nonatomic, copy) NSString *gender;

@end

TeamsViewController.m

// @interface TeamsViewController () {
//     NSString *teamName;
//    NSString *gender;
// }
// @end

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.gender = @"boys";
    self.teamName = @"Basketball";
}

// if you use properties, you don't have to write these methods; they'll be synthesized for you
//
// -(NSString *)gender {
//      NSLog(@"returning %@",gender);
//      return gender;
// }
//
// -(NSString *)teamName {
//     NSLog(@"returning %@",teamName);
//     return teamName;
// }

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (onBoys==true) {
        self.gender = @"boys";
    }
    else {
        self.gender = @"girls";
    }

    [self performSegueWithIdentifier:@"teamsPushSegue" sender:self];
}

Or if these are private properties, you could put the property declarations in the private class extension (but then I don't know why you bothered to write getter methods in the first place, if they were private).

For more information, see the Encapsulating Data section of the Programming with Objective-C guide.

Rob
  • 415,655
  • 72
  • 787
  • 1,044