Сообщение отправлено освобожденному экземпляру на объекте, который должен существовать - PullRequest
2 голосов
/ 27 июня 2011

[CFString isEqualToString:]: message sent to deallocated instance

Это ошибка, которую я получаю. У меня есть контроллер View со свойством NSMutableArray, и он содержит несколько объектов Player.

Тогда у меня есть метод, который переключается на другое представление, где я могу добавлять и удалять игроков. Когда я загружаю следующий вид, я передаю указатель на первый вид, второй вид. Затем я обновил массив, используя [previousView.playerList addObject:p];, где p - вновь созданный объект игрока.

Ошибка появляется, однако, когда я пытаюсь отобразить список игроков в виде таблицы второго вида. когда я пытаюсь получить доступ к [previousView.playerlist objectAtIndex:[indexPath row]];, я получаю сообщение об ошибке выше.

вот код:

Это первый вид, где он загружает второй и переходит к свойству второго.

- (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];
}

Здесь я инициализирую плеер и добавляю его в массив.

- (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];
}

А вот где я получаю свою ошибку

- (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;
}

Я получаю сообщение об ошибке в строке, где я устанавливаю текст ячейки. [cell.textLabel setText:[p playerName]];

Кто-нибудь знает, где я облажался? Я опубликую больше кода, если необходимо.

Я обрезал Player.m, чтобы включить только синтез и инициализацию, потому что остальное - МНОГО кода, который на самом деле не имеет отношения к этой ошибке, потому что она не вызывается.

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;
}

Также вот декларация массивов @property (nonatomic, retain) NSMutableArray *playerList;

1 Ответ

1 голос
/ 27 июня 2011

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;
}

Вы не удерживаете playerName.Обратите внимание, что хотя вы объявили свойство playerName как retain (а вместо него должно быть copy), вы не используете установщик свойств в -initWith….Вместо этого вы напрямую обращаетесь к переменной экземпляра поддержки.Поскольку вы непосредственно присваиваете playersName переменной экземпляра, вам нужно вручную отправить ее -retain (или, что еще лучше, -copy).

Проверьте, нужно ли вам это в других ваших объявленных свойствах,Кроме того, вы должны следовать идиоме:

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

в ваших инициализаторах.

Редактировать: вам необходимо внимательно просмотреть код с точки зрения практики управления памятью, так как выУтечка в более чем одном месте.Например, в:

- (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];
}

какова цель [self retain], и есть ли балансировка выпуска?

Другой пример: в:

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

выполучить +1 владение от +alloc, еще +1 от -retain, а массиву также принадлежит p, следовательно, еще +1.Вам следует заменить -retain на -autorelease, чтобы сбалансировать количество случаев владения этим объектом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...