开发者

Why is my instance variable nil even though I'm setting it?

I've got a custom class BoardMatchData, containing information about a chess match.

I've also got a custom UIViewController named BoardViewController, which is alloc'ed when a user selects a match from a list.

Here's a snippet from where I create the BoardViewController, set its delegate, and then set the new BoardMatchData:

    Games *selectedGame = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    if (!self.bvc) {
        NSLog(@"Alloc-ing a BVC");
        self.bvc = [[BoardViewController alloc] init];
        self.bvc.delegate = self;
    }
    [self.bvc setNewBoardMatchData:[MasterViewController boardMatchDataFromGame:selectedGame]];

When debugging, I can see this method setNewBoardMatchData being called, and it has valid data coming into it. However, later on within the BoardViewController, this boardMatchData always seems to开发者_高级运维 be nil. Here's the setNewBoardMatchData method:

- (void)setNewBoardMatchData:(BoardMatchData *)newBoardMatchData {
    NSLog(@"BMD is being set");
    if (self.boardMatchData != newBoardMatchData) {
        self.boardMatchData = newBoardMatchData;
        [self configureView];
    }
    if (self.masterPopoverController != nil) {
        [self.masterPopoverController dismissPopoverAnimated:YES];
    }

}

And within BoardViewController.h, I just have an instance variable:

BoardMatchData *boardMatchData;

A method declaration:

- (void)setNewBoardMatchData:(BoardMatchData *)newBoardMatchData;

And then at the top of BoardMatchData.m, I have:

@interface BoardViewController ()
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
@property (nonatomic,retain) BoardMatchData *boardMatchData; 
- (void)configureView;
@end

@synthesize boardMatchData = _boardMatchData;

...my intent here was to make sure that the setter was only ever being called by itself, and not by some other object.

Is there something wrong with how I'm trying to set self.boardMatchData?

I'm not doing any retains/releases because I'm using ARC.

Edit:

Caleb - I did that @synthesize statement as part of my flailing around trying to find this bug. Originally I had:

@synthesize boardMatchData;

... which I just switched back to. The behaviour is the same; self.boardMatchData always ends up nil, even after I've set it.

I think now I have only one ivar, boardMatchData, and I'm always accessing it through self.boardMatchData.

How do I prevent this from becoming nil?


@synthesize boardMatchData = _boardMatchData;

This says that the ivar the accessors should use is _boardMatchData, but you've also got an ivar named boardMatchData. If you're using the accessors, only _boardMatchData will be set. Since Objective-C automatically clears any ivars when your object is created, theboardMatchData ivar will always be nil.


Your comment (that you posted as an answer which you shouldn't do) suggests that you work on two different instances.

Here are a couple of possible reasons for this:

  1. self.bvc is just assign property instead of retain.
  2. You load one from within a nib and one is constructed in your code (as shown) - this is probably the most like one. Maybe you just forgot to wire up the outlet.
  3. Your set self.bvc to nil somewhere so that you keep creating new instances.


Aha; I found this question with an almost identical problem:

Objective-C – Retained property after being set is nil?

There was no conclusion to that one, but the last suggestion was to "try logging the address of self in -viewDidLoad and -viewWillAppear and -queueFinished. Something like NSLog(@"self is %p", self); and making sure they are the same."

I did that myself and now see that in initWithNibName/configureView/setNewBoardMatchData, I'm seeing one pointer for self, and then when viewDidLoad runs, I'm getting a different one!

I'm not sure how or why yet, but this clearly appears to be the problem (a new instance of my class is being instantiated AFTER I've set boardMatchData).

Edit:

While the above led me to the path of finding this bug (I was getting multiple versions of my BoardViewController), it's not the complete answer. I wanted to add here should anyone find this and be in the same position.

I was actually using storyboarding in Xcode4, and the Apple provided master-detail template with Core Data.

When I was instantiating my detail controller (BoardViewController), I was doing an alloc/init. I should have simply been referencing [segue destinationViewController], as the segue already instantiated a version for me. I did not provide enough context to actually get to the root

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜