2

[CFString isEqualToString:]: message sent to deallocated instance

This is the error I'm getting. I have a View controller with a Property that is an NSMutableArray and it contains some Player objects.

Then I have a method that switches to another view, where I can add and remove players. When I load the next view I pass a pointer to the first view, to the second view. I then updated the Array by using [previousView.playerList addObject:p]; where p is the newly created player object.

The error comes, however when I attempt to display the list of players in the second view's table view. when I try to access [previousView.playerlist objectAtIndex:[indexPath row]]; I get the error above.

here's the code:

This is in the first View, where it loads the second and passes itself to the property of the second.

- (IBAction) addPlayerButton:(id)sender {
    [self retain];
    PlayerListViewController *playerListViewController = [[PlayerListViewController alloc] init];
    playerListViewController.previousView = self;
    [UIView transitionFromView:self.view toView:playerListViewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
}

This is where I initialize the player and add it to the array.

- (IBAction)addPlayer:(id)sender {
    Player *p = [[[Player alloc] initWithPlayerName:playerNameField.text withOrder:[previousView.playerList count] withDelegate:previousView] retain];
    [previousView.playerList addObject:p];
    [playerNameField resignFirstResponder];
    [playerTableView reloadData];
}

And here is where I get my error

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"MyCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }
    Player* p = [previousView.playerList objectAtIndex:[indexPath row]];
    [cell.textLabel setText:[p playerName]];
    cell.accessoryType = UITableViewCellAccessoryCheckmark;

    return cell;
}

I'm getting the error on the line where I set the cell text. [cell.textLabel setText:[p playerName]];

Does anyone know where I'm screwing up? I will post more code if needed.

I trimmed Player.m to only include the Synthesis and Initalization, because the rest is A LOT of code, that doesnt really have to do with this error, because it isin't being called.

Player.h

@protocol playerProtocol <NSObject>

@optional
- (void) playerDied:(id)playerObject;
- (void) playerWasAdded:(id)playerObject;
- (void) playerLifeDidChange:(id)playerObject;
@end

@interface Player : NSObject {
    id <playerProtocol> delegate;
}
@property (nonatomic,retain) NSString *playerName;
@property (nonatomic, readwrite) int playerLife;
@property (nonatomic, readwrite) int playerPoison;
@property (nonatomic, readwrite) int order;
@property (nonatomic, readwrite) Boolean invincible;
@property (nonatomic, assign) id <playerProtocol>delegate;
@property (nonatomic, retain) UIView *viewPane;
@property (nonatomic) Boolean shown;
@property (nonatomic, readwrite) int minusButton;
@property (nonatomic, readwrite) int plusButton;
@property (nonatomic, retain) UIImageView *readout;
@property (nonatomic, retain) NSArray *playerLifeNumerals;


- (id) initWithPlayerName:(NSString *)playersName withOrder:(int)Order withDelegate:(id)d;
- (void) setPlayerLife:(int)pplayerLife;
- (void) setPlayerPoison:(int)pplayerPoison;
- (NSArray *) getLifeNumeralsFromPlayer:(Player *)playerObject;

@end

Player.m

@implementation Player

@synthesize playerLife, playerName, playerPoison, order, delegate, invincible, viewPane, readout, shown, minusButton, plusButton, playerLifeNumerals;

#pragma mark - Custom Initalizer

- (id) initWithPlayerName:(NSString *)playersName withOrder:(int)Order withDelegate:(id)d {

    [super init];
    delegate = d;
    playerLife = 20;
    playerPoison = 0;
    order = Order;
    playerName = playersName;
    invincible = NO;
    [delegate playerWasAdded:self];
    viewPane = nil;
    readout = nil;
    shown = NO;
    return self;
}

Also here's the arrays declaration @property (nonatomic, retain) NSMutableArray *playerList;

Weston
  • 1,481
  • 1
  • 11
  • 31
  • You should probably post the declaration and implementation of `Player`. –  Jun 27 '11 at 12:06

1 Answers1

1

In:

- (id) initWithPlayerName:(NSString *)playersName withOrder:(int)Order withDelegate:(id)d {

    [super init];
    delegate = d;
    playerLife = 20;
    playerPoison = 0;
    order = Order;
    playerName = playersName;
    invincible = NO;
    [delegate playerWasAdded:self];
    viewPane = nil;
    readout = nil;
    shown = NO;
    return self;
}

you are not retaining playerName. Note that although you’ve declared your playerName property as retain (and it should be copy instead), you’re not using the property setter in -initWith…. Instead, you’re directly accessing the backing instance variable. Since you’re directly assigning playersName to the instance variable, you need to manually send it -retain (or, better yet, -copy).

Check whether you need this in your other declared properties. Also, you should follow the idiom:

self = [super init];
if (self) { … }
return self;

in your initialisers.

Edit: you need to carefully review your code with regard to memory management practices since you’re leaking in more than one place. For example, in:

- (IBAction) addPlayerButton:(id)sender {
    [self retain];
    PlayerListViewController *playerListViewController = [[PlayerListViewController alloc] init];
    playerListViewController.previousView = self;
    [UIView transitionFromView:self.view toView:playerListViewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
}

what’s the purpose of [self retain], and is there a balancing release?

Another example: in:

Player *p = [[[Player alloc] initWithPlayerName:playerNameField.text withOrder:[previousView.playerList count] withDelegate:previousView] retain];
[previousView.playerList addObject:p];

you get +1 ownership from +alloc, another +1 from -retain, and the array also owns p, hence another +1. You should replace -retain with -autorelease to balance the number of times you’re taking ownership of that object.

  • Yea i was just trying to find the bug before i played with retains and releases on this code. it usually takes me a while to get it right. – Weston Jun 27 '11 at 12:37
  • Worked GREAT you are a GOD!!! i wish i could give you +100. that has been bugging me all weekend. – Weston Jun 27 '11 at 14:22
  • One more question regarding this code if you don't mind, do you know of a good tutorial that explains when i should use copy or retain? my iOS programming book really only explained retain. – Weston Jun 27 '11 at 14:24
  • 1
    @Kron There are a few questions on Stack Overflow about it, one of which is: [NSString property: copy or retain?](http://stackoverflow.com/q/387959/557219) –  Jun 28 '11 at 00:19