web-dev-qa-db-fra.com

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

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

Voici le code:

Object.h

NSMutableArray *array;

@property (copy) NSMutableArray *array;

Objet.m

@synthesize array;

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

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

J'ai testé anObject et l'initialisation fonctionne parfaitement, mais l'erreur continue à se produire lorsque j'essaie d'ajouter addObject: to self.array.

2010-07-10 11: 52: 55.499 MyApp [4347: 1807] - [__ NSArrayI addObject:]: sélecteur non reconnu envoyé à l'instance 0x184480.

2010-07-10 11: 52: 55.508 MyApp [4347: 1807] *** Application terminée en raison d'une exception non interceptée 'NSInvalidArgumentException', raison: '- [__ NSArrayI addObject:]: sélecteur non reconnu envoyé à l'instance 0x184480'

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

67
Zak

J'aimerais saluer Georg Fritzsche. J'ai fini par avoir besoin d'utiliser (copie) au lieu de (conserver), et je n'aurais pas su quoi faire sans son apport.

//@property (copy) NSMutableArray *array;
@property (nonatomic, copy) NSMutableArray *array; //overridden method is non-atomic as it is coded and should be reflected here.

Si vous souhaitez utiliser (copier) 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]; // unnecessary as noted by Georg Fritzsche
    }

    return;
}

REMARQUE: vous recevrez un avertissement concernant le compilateur: Types Objective-C incompatibles initialisant 'struct NSArray *', attendu 'struct NSMutableArray *' J'ai choisi de déclarer le paramètre newArray sous la forme (NSArray *) tableau passé et correctement copié dans votre variable (NSMutableArray *). Si vous souhaitez déclarer le paramètre newArray en tant que (NSMutableArray *), vous devez tout de même laisser la méthode mutableCopy en place pour obtenir les résultats souhaités.

Bravo à Georg!Z@K!

11
Zak

Le programme de synthèse synthétisé pour @property (copy) envoie un message copy au tableau, ce qui entraîne une copie immuable.

Vous n'avez pas d'autre choix que de mettre en œuvre le paramètre vous-même, comme detail dans le guide Objective-C.

82
Georg Fritzsche

Alors que je corrigeais mon post, une pensée me vint à l'esprit et je répondis à ma propre question. Cette résolution était assez obscure pour que je décide d'aller de l'avant, de créer le message et d'y répondre moi-même (pour que les autres débutants, comme moi, ne soient pas bloqués).

Mon erreur était dans ...

@property (copy) NSMutableArray *array;

ça aurait dû être ...

@property (retain) NSMutableArray *array;

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

Comme nous le savons tous...

mutableArray = [mutableArray copy];

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

mutableArray = [mutableArray mutableCopy];

Et c'était la source de mon problème. En changeant simplement la propriété @ de (copie) à (conserver), j'ai résolu mon problème.

72
Zak

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

Ce qui se passait, c’était que j’étais en train d’archiver le tableau mutable (car il contient des objets personnalisés) pour une utilisation future et lors du décodage, il renvoie une copie immuable.

J'espère que ça aide quelqu'un.

3
OlivaresF

Avoir quelques index (dans un tableau de données ailleurs) et je voulais les avoir dans l’ordre numérique (pour une bonne raison). Crashing jusqu'à ce que mutableCopy soit ajouté à la fin. Totalement perplexe, jusqu'à ce que je me souvienne que l'utilisation de Objective-C literal @ [] renvoie 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!

3
JOM

Je me suis fait mordre par cette exception pour une faute de frappe que j'ai faite, cela sauvera peut-être quelqu'un 5 min. de leur temps:

J'ai écrit:

NSMutableArray *names = [NSArray array];

au lieu de:

NSMutableArray *names = [NSMutableArray array];

Le compilateur n’a aucun problème avec cela, car NSMutableArray est également un NSArray, mais il se bloque lors de la tentative d’ajout d’un objet.

0
marmor

J'ai eu une erreur similaire en disant: sélecteur non reconnu envoyé à l'instance pour le tableau NSMutable .. Après avoir traversé beaucoup de choses, j'ai réalisé que j'utilisais mon tableau mutable en tant que propriété

@property (assign, nonatomic) NSMutableArray *myMutableArray;

en copiant-collant et en ne faisant pas attention, cela causait le problème.

La solution que nous avons choisie est le type fort (vous pouvez le remplacer par un autre type, tel que fort/faible, etc. selon vos besoins). Donc, la solution dans mon cas était:

@property (strong, nonatomic) NSMutableArray *myMutableArray;

Alors, soyez prudent lors du copier-coller! Vérifiez une fois.

0
Priyanka

L'erreur est due à la tentative d'ajouter un objet à un type NSMutableArray qui pointait en fait sur un objet NSArray. Ce type de scénario est présenté dans certains codes de démonstration ci-dessous:

NSString *test = @"test";
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
[mutableArray addObject:test];
NSArray *immutableArray = [[NSArray alloc] init];
mutableArray = immutableArray;
[mutableArray addObject:test]; // Exception: unrecognized selector

D'après le code ci-dessus, il est facile de voir qu'un type de sous-classe est en train d'être affecté à un type de superclasse. En Java, par exemple, cela aurait immédiatement été signalé comme une erreur (erreur de conversion entre les types) et le problème résolu assez rapidement. Pour être juste envers Objective-C, un avertissement est émis lors de la tentative d’exécution d’une tâche incompatible. Cependant, cela ne semble tout simplement pas suffire parfois et le résultat peut être très pénible pour les développeurs. Heureusement, cette fois-ci, ce n’est pas moi qui ai porté le plus de souffrances: P

0
Baljeet Singh