2010-09-30 17 views

risposta

131

Esistono diversi casi d'uso per un set. È possibile enumerare tramite (ad esempio con enumerateObjectsUsingBlock o NSFastEnumeration), chiamare containsObject per verificare l'appartenenza, utilizzare anyObject per ottenere un membro (non casuale) o convertirlo in un array (in nessun ordine particolare) con allObjects.

Un set è appropriato quando non si desidera duplicare, non si preoccupa per l'ordine e si desidera testare rapidamente l'iscrizione.

+7

Puoi anche cercare un oggetto conosciuto da un potenziale duplicato inviando al set un messaggio 'membro:'. Se restituisce 'nil', il set non contiene un oggetto uguale a quello che hai passato; se restituisce un puntatore all'oggetto, il puntatore restituito si trova già nell'oggetto nel set. Gli oggetti nel set devono implementare 'hash' e' isEqual: 'perché questo sia utile. –

+0

@PeterHosey Non penso che 'hash' _needs_ sia implementato; sarebbe molto più veloce se lo facessi. – fumoboy007

+2

@ fumoboy007: per l'archiviazione in un set o l'utilizzo come chiave in un dizionario, sì lo fa. Dalla documentazione di 'hash' nel protocollo NSObject:" Se due oggetti sono uguali (come determinato dal metodo 'isEqual:'), devono avere lo stesso valore di hash. "Attualmente, le implementazioni di NSObject di' hash' e 'isEqual : 'usa l'identità dell'oggetto (indirizzo). Se si esegue l'override di 'isEqual:', si sta impostando la possibilità di oggetti che non sono identici ma uguali, il quale, se non si esegue l'override di 'hash', avrà comunque hash diversi. Ciò viola il requisito che gli oggetti uguali abbiano uguali hash. –

29

NSSet non ha un metodo objectAtIndex:

Prova allObjects chiamata che restituisce un NSArray di tutti gli oggetti.

+0

hai idea se l'array restituito è ordinato? in altre parole, se io aggiungo oggetti al set usando "setByAddingObject", e ho usato "allObjects", sono? gli elementi dell'array ordinati nell'ordine ho aggiunto gli oggetti? – iosMentalist

+0

ordina semplicemente l'array risultante con un NSSortPredicate e starai bene – Jason

+0

Se ti interessa solo un oggetto specifico, usa l'approccio filteredSetUsingPredicate. – akw

6

NSSet utilizza il metodo isEqual: (che gli oggetti inseriti in quell'insieme devono eseguire l'override, in aggiunta, il metodo hash) per determinare se un oggetto si trova all'interno di esso.

Così, per esempio se si dispone di un modello di dati che definisce la sua unicità da un valore di id (per esempio la proprietà è:

@property NSUInteger objectID; 

allora si sarebbe attuare IsEqual: come

- (BOOL)isEqual:(id)object 
{ 
    return (self.objectID == [object objectID]); 
} 

ed è possibile implementare l'hash:

- (NSUInteger)hash 
{ 
return self.objectID; // to be honest, I just do what Apple tells me to here 
         // because I've forgotten how Sets are implemented under the hood 
} 

Quindi, è possibile ottenere un oggetto con tale ID (nonché controllare per se è nella NSSet) con:

MyObject *testObject = [[MyObject alloc] init]; 
testObject.objectID = 5; // for example. 

// I presume your object has more properties which you don't need to set here 
// because it's objectID that defines uniqueness (see isEqual: above) 

MyObject *existingObject = [mySet member: testObject]; 

// now you've either got it or existingObject is nil 

Ma sì, l'unico modo per ottenere qualcosa da un NSSet è da considerare quella che definisce la sua unicità, in primo luogo.

Non ho provato cosa è più veloce, ma evito di usare l'enumerazione perché potrebbe essere lineare mentre usando il membro: il metodo sarebbe molto più veloce. Questo è uno dei motivi per preferire l'uso di NSSet anziché di NSArray.

12

NSArray *myArray = [myNSSet allObjects];

MyObject *object = [myArray objectAtIndex:(NSUInteger *)] 

sostituire NSUInteger con l'indice del vostro oggetto desiderato.

+1

Dovrebbe essere: MyObject * object = [oggetto myArrayAtIndex: (NSUInteger *)] –

17

è possibile utilizzare filteredSetUsingPredicate se si dispone di un tipo di identificatore univoco per selezionare l'oggetto desiderato.

Innanzitutto creare il predicato (supponendo che il ID unico nell'oggetto si chiama "identificativo" ed è un NSString):

NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier]; 

e scegliere l'oggetto che utilizza il predicato:

NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject; 
0
for (id currentElement in mySet) 
{ 
    // ** some actions with currentElement 
} 
4

Per Swift3 & iOS10:

//your current set 
let mySet : NSSet 
//targetted index 
let index : Int 
//get object in set at index 
let object = mySet.allObjects[index] 
Problemi correlati