2010-07-10 16 views
66

Ho provato a inizializzare il mio NSMutableArray in 100 modi da domenica e NULLA funziona per me. Ho provato a impostarlo uguale a un NSMutableArray appena allocato e inizializzato, semplicemente allocando, inizializzando la variabile da sola, ogni combinazione a cui potevo pensare e sempre lo stesso risultato.NSMutableArray addObject: - [__ NSArrayI addObject:]: selettore non riconosciuto inviato all'istanza

Ecco il codice:

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

NOTA: In debug "anObject" non è nullo in fase di esecuzione ...

Ho testato anObject ed è L'inizializzazione funziona bene, ma continuo a ricevere l'errore qui sotto quando Provo ad aggiungereObject: a self.array.

2010-07-10 11: 52: 55,499 Miaapp [4347 1807] - [__ NSArrayI addObject:]: selettore non riconosciuto inviato ad esempio 0x184480

2010-07-10 11: 52: 55,508 MyApp [4347: 1807] *** terminazione app a causa di eccezione non identificata 'NSInvalidArgumentException', la ragione: '- [__ NSArrayI addObject:]: selettore non riconosciuto inviato ad esempio 0x184480'

qualcuno ha idea di cosa sta andando male ?

risposta

11

Vorrei portare il mio cappello a Georg Fritzsche.Alla fine ho dovuto usare (copiare) invece di (conservare), e non avrei saputo cosa fare senza il suo contributo.

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

Se si desidera utilizzare (copia) su un oggetto mutabile è necessario eseguire l'override del metodo "setter" nel modo seguente ...

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

    if (array != newArray) { 
     [array release]; 
     array = [newArray mutableCopy]; 
//  [array retain]; // unnecessary as noted by Georg Fritzsche 
    } 

    return; 
} 

NOTA: Si otterrà un avviso del compilatore: Obiettivo incompatibile -C tipi di inizializzazione 'struct NSArray *', previsto 'struct NSMutableArray *' Ho scelto di dichiarare il parametro newArray come un (NSArray *), perché ti viene data la flessibilità di far passare qualsiasi array e copiarlo correttamente sul tuo (NSMutableArray *) variabile. Se si desidera dichiarare il parametro newArray come un (NSMutableArray *), sarà comunque necessario lasciare il metodo mutableCopy in posizione per ottenere i risultati desiderati.

Cheers to Georg! Z @ K!

+0

Si noti che la dichiarazione di proprietà non deve corrispondere al tipo di ivar, quindi si dovrebbe usare' @property (nonatomic, copy) NSArray * array; nel tuo caso. Nota inoltre che la tua proprietà è implicitamente atomica, ma l'implementazione del tuo setter non è - vedi [Atomicity] (http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html # // apple_ref/doc/uid/TP30001163-CH17-SW28). –

+1

Infine, '-mutableCopy' restituisce già un'istanza mantenuta, quindi non è necessario' [array retain] '- vedere [Politica proprietà degli oggetti] (http://developer.apple.com/mac/library/documentation/Cocoa /Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043-SW1). –

+0

Grazie ancora, signor Fritzsche. Ero curioso di quella riserva in più, ma sembrava funzionare nel mio programma. Apparentemente ho un bug altrove. : -/Tu sei l'uomo, grazie per aver contribuito a questo post e, inavvertitamente, il mio programma; Apprezzo il tuo tempo! Cordiali saluti, Z @ K! – Zak

81

Il setter sintetizzato per @property (copy) invia un messaggio copy all'array, che risulta in una copia immutabile.

Non avete altra scelta che implementare il setter da soli qui, come detailed nella guida Objective-C.

+0

CORRETTO ASSOLUTAMENTE!L'ho capito mentre stavo scrivendo il mio post e ho pubblicato la mia risoluzione qui sotto. Non ho davvero pensato di scavalcare il setter, ma nel mio caso non ho davvero bisogno di una copia quindi la mia soluzione ha funzionato per me. Grazie per la risposta rapida! - Z @ K! – Zak

+1

Il collegamento alla guida Objective-C è interrotto. – johnnieb

69

Mentre stavo leggendo il mio post, mi è venuto in mente un pensiero e ho risposto alla mia domanda. Questa risoluzione è stata abbastanza oscura che ho deciso di andare avanti, creare il post e rispondere a me stesso (così tutti i neofiti, come me, non saranno appesi).

mio errore è stato in ...

@property (copy) NSMutableArray *array; 

avrebbe dovuto essere ...

@property (retain) NSMutableArray *array; 

L'errore non stava accadendo nel mio modo stava eseguendo il mio codice, ma piuttosto nella modo l'anObject stava tentando di "copiare" l'array NSMutableArray.

Come tutti sappiamo ...

mutableArray = [mutableArray copy]; 

non è sempre (o mai, nella mia esperienza) pari a ...

mutableArray = [mutableArray mutableCopy]; 

e questa era la fonte del mio problema. Commettendo semplicemente @property da (copia) a (conserva) ho risolto il mio problema.

+0

Stavo avendo lo stesso problema, ho risolto il mio cambiamento di proprietà da copia per conservare ... @Zak +1 per la risposta. – Rupesh

+0

Dovresti segnare come risposta accettata. – NathanAldenSr

+1

'mutableCopy' ha appena salvato il mio live – michaelsnowden

-4

Questa eccezione può verificarsi se uno degli oggetti nell'array è nullo.

+1

Non questo particolare errore, no. Si ottiene un'eccezione diversa se si tenta di inserire un oggetto nullo. –

+0

Oltre a ciò, gli array possono contenere perfettamente NSNull. – stephencelis

3

Stavo ottenendo lo stesso errore, anche se le mie proprietà erano forti (usando ARC) e ho assegnato l'array con NSMutableArray.

Quello che stava accadendo era che stavo archiviando l'array mutabile (dato che contiene oggetti personalizzati) per un uso futuro e quando lo decodifica, restituisce una copia immutabile.

Spero che aiuti chiunque là fuori.

3

Hanno alcuni indici (in un array di dati altrove) e volevano averli in ordine numerico (per una buona ragione). Crashing fino all'aggiunta di mutableCopy alla fine. Completamente perplesso, fino a quando non ho ricordato che l'utilizzo di Objective-C letteral @ [] restituisce un array non modificabile.

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

Grazie, Zak!

0

Sono stato morso da questa eccezione per un errore di battitura che ho creato, forse salverà qualcuno 5 min. del loro tempo:

ho scritto:

NSMutableArray *names = [NSArray array]; 

invece di:

NSMutableArray *names = [NSMutableArray array]; 

Il compilatore non ha alcun problema con quello perché NSMutableArray è anche un NSArray, ma si blocca quando si cerca di aggiungere un oggetto.

0

L'errore si è verificato in seguito al tentativo di aggiungere un oggetto a un tipo NSMutableArray che stava effettivamente puntando a un oggetto NSArray. Questo tipo di scenario è mostrato in qualche codice demo di seguito:

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

Dal codice di cui sopra, è facile vedere che un tipo di sottoclasse viene assegnato a un tipo superclasse. In Java, ad esempio, questo sarebbe stato immediatamente contrassegnato come un errore (errore di conversione tra tipi) e il problema si risolse abbastanza rapidamente. Per essere onesti con Objective-C, viene dato un avvertimento quando si tenta di eseguire un compito incompatibile, tuttavia, questo semplicemente non sembra essere abbastanza a volte e il risultato può essere un vero dolore per gli sviluppatori. Fortunatamente, questa volta, non sono stato io a sopportare la maggior parte di questo dolore: P

Problemi correlati