Trasportato in un piccolo problema interessante. Stavo scrivendo un metodo per filtrare un array per gli oggetti unici:Conversione di NSArray in NSSet, trasferimento di istanze di classi personalizzate in modo incoerente
- (NSArray*)distinctObjectsByAddress {
NSSet* uniqueSet = [NSSet setWithArray:self];
NSArray* retArray = [uniqueSet allObjects];
return retArray;
}
e ha scritto uno unit test per controllare:
- (void)testDistinctObjectsByAddress5 {
Person* adam1 = [[Person alloc] initWithFirstName:@"adam" lastName:@"adam" andParent:nil];
Person* adam2 = [[Person alloc] initWithFirstName:@"adam" lastName:@"adam" andParent:nil];
testPersonArray = [NSArray arrayWithObjects:adam1,adam2, nil];
NSArray* checkArray = [testPersonArray distinctObjectsByAddress];
STAssertEquals([checkArray count], [testPersonArray count], @"Array %@ counts should match %@ %@",checkArray,adam1,adam2);
}
Abbastanza semplice. La parte interessante è che circa l'80-90% delle volte il test passa e ogni tanto fallisce perché il metodo distinctObjectsByAddress
restituisce solo un oggetto. Sono stato in grado di rintracciarlo alla chiamata [NSSet setWithArray:self]
ma sono anche stato in grado di verificare che gli oggetti a due persone siano due oggetti diversi (almeno hanno un indirizzo diverso). Suppongo che lo setWithArray:
stia semplicemente facendo un confronto di base, ma non capisco perché a volte produca due oggetti come dovrebbe e talvolta ne produce solo uno.
Qualcosa che ho appena provato stava cambiando adam2
in modo che il nome e il cognome non corrispondessero esattamente allo adam1
. Questo sembra risolvere l'errore. Questo indica una sorta di ottimizzazione del compilatore quando gli oggetti sono logicamente uguali?
Direi che il problema è con Person e come implementa i metodi di hash e di uguaglianza utilizzati da NSSet. –
Userà 'isEqual:' come definito dal protocollo 'NSObject' per confrontare gli oggetti; l'hai implementato o 'hash' su' Persona'? – Tommy
Oltre al problema dell'hash, non stai testando esplicitamente adam1 e adam2 per zero. Se uno di tanto in tanto non riesce a inizializzare, ciò spiegherebbe il fallimento del test. – bneely