2010-01-05 4 views
1

J'obtiens cette erreur en essayant de voir le contenu d'un NSMutableArray:EXC_BAD_ACCESS lors du débogage

Program received signal EXC_BAD_ACCESS, Could not access memory. 
Reason: KERN_PROTECTION_FAILURE at address: 0x00000021 
0x94d5a688 in objc_msgSend() 

ViewController.h:

@interface PeopleViewController : UITableViewController { 
    NSMutableArray *people; 
} 

@property (nonatomic, retain) NSMutableArray *people; 

ViewController.m:

@implementation PeopleViewController 

@synthesize people; 

Dans viewDidLoad:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // initialize our people array with an autoreleased object 
    people = [NSMutableArray array]; 

... Populate the people array with Person objects. 

} 

Quand je suis au point où je modifier le contenu d'une cellule dans le tableview, je ne peux pas accéder au tableau de personnes gdb lors de la frappe « po self.people »:

Person *person = [[Person alloc] init]; 
person = [self.people objectAtIndex: indexPath.row]; // <--- 'po self.people' called 
cell.textLabel.text = person.personName; 

Des idées pour lesquelles je ne peux pas y accéder?

Répondre

7

La ligne

people = [NSMutableArray array]; 

retourne un tableau autoreleased qui sortira sur la prochaine itération de la boucle de courant de l'exécution. Vous devez conserver cela:

people = [[NSMutableArray array] retain]; 

et bien sûr de le libérer dans votre méthode dealloc.

Cependant: Les ingénieurs d'Apple ont souvent mentionné dans les conférences pour éviter les instances auto-libérées comme celle-ci autant que possible dans l'iPhone, pour des raisons de performances. Essayez d'utiliser alloc/init à la place:

people = [[NSMutableArray alloc] initWithCapacity:1]; 

avec la version correspondante dans la méthode dealloc. Dans ce cas, vous n'avez même pas besoin de le conserver (init renvoie une instance avec un nombre de retain de 1, ce qui est ce dont vous avez besoin).

Et le commentaire de justin est correcte: vous devriez le faire à la place:

Person *person = [people objectAtIndex:indexPath.row]; 
cell.textLabel.text = person.personName; 

et cela devrait fonctionner.

+0

Je ne pense pas que le message de conservation soit nécessaire, car la propriété est marquée comme "retenue". –

+3

Mais la propriété n'est pas utilisée ici, la variable d'instance est en cours d'accès directement, donc la propriété n'a pas d'importance. – jbrennan

+0

Exactement comme jbrennan dit: self.person signifie un appel à la méthode setter de la propriété, alors que "person" tout seul est juste une assignation à l'ivar. –

4

est-ce que indexPath.row> [nombre de personnes]?

Aussi, pourquoi fais-tu cela:

personne * personne = [[personne alloc] init]

Vous allouer de la mémoire, puis en pointant sur la mémoire complètement différente.

+0

Absolument correct. Fuite d'une instance à la fois. –

1

Vous pouvez éviter d'avoir à vous soucier des propriétés de conservation en utilisant la notation self pour appeler les méthodes accesseur et setter créées par la directive @synthesize.

Lorsque vous définissez la propriété people directement dans viewDidLoad, elle définit la propriété mais ne fait rien pour la gestion de la mémoire. Toutefois, si vous le définissez avec self.people, vous appelez en fait la méthode Setter synthétisée qui, en raison du paramètre retain de la directive @property, conservera automatiquement le tableau affecté.En outre, je recommanderais toujours d'utiliser -[NSMutableArray initWithCapacity:] au lieu d'un init nu. C'est l'initialiseur réel pour la classe. Vous pouvez l'appeler avec juste '1' si vous ne savez pas quelle sera la taille. Dans le passé, j'ai vu un problème étrange se pose juste en utilisant nu.

+0

Merci pour les têtes sur l'initialiseur désigné de NSMutableArray, j'ai corrigé cela dans ma réponse. –

Questions connexes