67 votes

NSMutableArray addObject: -[__NSArrayI addObject:]: sélecteur non reconnu envoyé à l'instance

J'ai essayé d'initialiser mon NSMutableArray de 100 façons depuis dimanche, et RIEN ne fonctionne pour moi. J'ai essayé de le mettre égal à un NSMutableArray nouvellement alloué et initialisé, juste allouer, initialiser la variable par elle-même, chaque combinaison possible que je pouvais penser et toujours le même résultat.

Voici le code:

Object.h

NSMutableArray *array;

@property (copy) NSMutableArray *array;

Object.m

@synthesize array;

if ( self.array ) {
    [self.array addObject:anObject];
}
else {
    self.array = [NSMutableArray arrayWithObjects:anObject, nil];
}

NOTE: En mode débogage "anObject" n'est PAS nil au moment de l'exécution...

J'ai testé anObject et l'initialisation fonctionne très bien, mais je continue à obtenir l'erreur ci-dessous quand j'essaie d'ajouter un addObject: à self.array.

2010-07-10 11:52:55.499 MyApp[4347:1807] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x184480

2010-07-10 11:52:55.508 MyApp[4347:1807] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI addObject:]: unrecognized selector sent to instance 0x184480'

Est-ce que quelqu'un a une idée de ce qui ne va pas?

84voto

Georg Fritzsche Points 59185

Le setter synthétisé pour @property (copy) envoie un message copy à l'array, ce qui donne une copie immuable.

Vous n'avez pas d'autre choix que d'implémenter vous-même le setter ici, comme détaillé dans le guide Objective-C.

0 votes

ABSOLUMENT CORRECT! Je m'en suis rendu compte en écrivant mon message, et j'ai posté ma résolution ci-dessous. Je n'ai pas vraiment envisagé de remplacer le setter, mais dans mon cas je n'ai pas vraiment besoin d'une copie donc ma solution a fonctionné pour moi. Merci pour la réponse rapide! - Z@K!

1 votes

Le lien vers le guide Objective-C est cassé.

75voto

Zak Points 2223

En relisant mon article, une pensée m'est venue et j'ai répondu à ma propre question. Cette résolution était assez obscure pour moi de décider de continuer, de créer l'article et d'y répondre moi-même (afin que d'autres débutants, comme moi, ne se retrouvent pas bloqués).

Mon erreur était dans...

@property (copy) NSMutableArray *array;

cela aurait dû être...

@property (retain) NSMutableArray *array;

L'erreur ne se produisait pas dans la façon dont j'exécutais mon code, mais plutôt dans la façon dont l'objet essayait de "copier" le NSMutableArray array.

Comme nous le savons tous...

mutableArray = [mutableArray copy];

n'est pas toujours (ou jamais, à mon expérience) égal à...

mutableArray = [mutableArray mutableCopy];

Et voilà la source de mon problème. En simplement passant de (copy) à (retain) dans @property, j'ai résolu mon problème.

0 votes

Je rencontrais le même problème, je l'ai résolu en changeant la propriété de "copy" à "retain"... @Zak +1 pour ta réponse.

1 votes

mutableCopy vient de sauver ma vie

11voto

Zak Points 2223

Je voudrais tirer mon chapeau à Georg Fritzsche. J'ai fini par avoir besoin d'utiliser (copy) plutôt que (retain), et je n'aurais pas su quoi faire sans ses contributions.

//@property (copy) NSMutableArray *array;
@property (nonatomic, copy) NSMutableArray *array; //la méthode remplacée est non atomique car elle est codée et cela devrait se refléter ici.

Si vous souhaitez utiliser (copy) sur un objet mutable, vous devez remplacer la méthode "setter" comme suit...

- (void)setArray:(NSArray *)newArray {

    if ( array != newArray ) { 
        [array release];
        array = [newArray mutableCopy];
//      [array retain]; // inutile comme l'a noté Georg Fritzsche
    }

    return;
}

REMARQUE : Vous obtiendrez un avertissement du compilateur : Types Objective-C incompatibles initialisant 'struct NSArray *', prévu 'struct NSMutableArray *'. J'ai choisi de déclarer le paramètre newArray comme un (NSArray *), car vous avez la flexibilité de passer n'importe quel tableau et de le copier correctement dans votre variable (NSMutableArray *). Si vous souhaitez déclarer le paramètre newArray comme un (NSMutableArray *), vous devrez quand même laisser la méthode mutableCopy en place pour obtenir les résultats souhaités.

Bravo à Georg! Z@K!

0 votes

Notez que la déclaration de votre propriété n'a pas besoin de correspondre au type de variable d'instance, vous devriez donc utiliser @property (nonatomic, copy) NSArray *array; dans votre cas. Notez également que votre propriété est implicitement atomique, mais l'implémentation de votre setter ne l'est pas - voir Atomicity.

1 votes

Enfin, -mutableCopy retourne déjà une instance conservée, donc il n'est pas nécessaire d'utiliser [array retain] - voir Politique de propriété des objets.

0 votes

Merci encore, Mr. Fritzsche. J'étais curieux de cette rétention supplémentaire, mais cela semblait fonctionner dans mon programme. Apparemment, j'ai un bug ailleurs. :-/ Vous êtes l'homme, merci de contribuer à ce message et, involontairement, à mon programme; Je vous apprécie! Sincèrement, Z@K!

3voto

OlivaresF Points 652

J'obtenais la même erreur, même si mes propriétés étaient fortes (en utilisant ARC) et que j'avais alloué le tableau avec NSMutableArray.

Ce qui se passait, c'est que j'archivais le tableau mutable (car il contient des objets personnalisés) pour une utilisation future et lors du décodage, cela retourne une copie immuable.

En espérant que cela aide quelqu'un là-bas.

3voto

JOM Points 4282

Avoir certains index (dans un tableau de données ailleurs) et les vouloir dans l'ordre numérique (pour une bonne raison). S'écraser jusqu'à ce que mutableCopy soit ajouté à la fin. Totalement perplexe, jusqu'à ce que je me rappelle qu'utiliser le littéral Objective-C @[] retourne un tableau non mutable.

NSMutableArray *a = [@[@(self.indexA), @(self.indexB)] mutableCopy];
NSLog(@"%@", a);
[indexArray sortUsingComparator: ^(NSNumber *obj1, NSNumber *obj2) {
    return [obj1 compare:obj2];
}];
NSLog(@"%@", a);

Merci, Zak!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X