2010-09-30 15 views

Odpowiedz

131

Istnieje kilka przypadków użycia dla zestawu. Można wyliczyć (np. Z enumerateObjectsUsingBlock lub NSFastEnumeration), zadzwonić pod numer containsObject, aby przetestować członkostwo, użyć anyObject, aby uzyskać człon (nie losowy) lub przekonwertować go do tablicy (w dowolnej kolejności) z allObjects.

Zestaw jest odpowiedni, gdy nie chcesz duplikatów, nie zależy Ci na zamówieniu i chcesz przeprowadzić szybkie testy członkostwa.

+7

Można również wyszukać znany obiekt przez potencjalny duplikat, wysyłając zestawowi komunikat 'member:'. Jeśli zwróci 'nil', zestaw nie zawiera obiektu równego temu, który przekazałeś; jeśli zwraca wskaźnik obiektu, to wskaźnik, który zwraca, jest do obiektu już w zestawie. Obiekty w zestawie muszą zaimplementować 'hash' i' isEqual: ', aby było to użyteczne. –

+0

@PeterHosey Nie sądzę, że 'hash' _needs_ do wdrożenia; Gdybyś to zrobił, poszedłby o wiele szybciej. – fumoboy007

+2

@ fumoboy007: Do przechowywania w zestawie lub użycia jako klucz w słowniku, tak to robi. Z dokumentacji 'hash' w protokole NSObject:" Jeśli dwa obiekty są równe (zgodnie z metodą 'isEqual:'), muszą mieć tę samą wartość skrótu. "Obecnie implementacje NSObject' hash' i 'isEqual : 'użyj tożsamości obiektu (adresu). Jeśli zastąpisz 'isEqual:', ustawiasz możliwość, że obiekty nie są identyczne, ale są równe, co jeśli nie zastąpisz 'hash', nadal będzie mieć różne skróty. To narusza wymóg, aby równe obiekty miały równe skróty. –

29

NSSet nie ma metody objectAtIndex:

Spróbuj zadzwonić allObjects który zwraca NSArray wszystkich obiektów.

+0

czy masz pojęcie, czy zwrócona tablica jest zamówiona? innymi słowy, jeśli dodaję obiekty do zestawu za pomocą "setByAddingObject", a ja użyłem "allObjects", to czy? elementy w tablicy uporządkowane w kolejności dodałem obiekty? – iosMentalist

+0

posortuj wynikową tablicę za pomocą NSSortPredicate, a wszystko będzie dobrze – Jason

+0

Jeśli interesuje Cię tylko jeden konkretny obiekt, lepiej użyj metody filtersSetUsingPredicate. – akw

6

NSSet używa metody isEqual: (którą obiekty, które umieszczasz w tym zestawie, musi przesłonić dodatkowo metodę hash), aby określić, czy obiekt znajduje się w środku.

Tak więc, na przykład, jeśli masz model danych, który określa jego wyjątkowość o wartość id (słownie nieruchomość jest:

@property NSUInteger objectID; 

następnie chcesz zaimplementować IsEqual: jak

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

i można wdrożyć 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 
} 

Następnie można uzyskać obiekt o takim identyfikatorze (a także czek na czy to w NSSet) z:

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 

Ale tak, to jedyny sposób, aby dostać coś z NSSet jest rozważając to, co określa jego wyjątkowość w pierwszej kolejności.

Nie testowałem tego, co jest szybsze, ale unikam używania wyliczeń, ponieważ może to być metoda liniowa, natomiast użycie metody member: metoda będzie znacznie szybsza. To jeden z powodów, dla których warto wybrać NSSet zamiast NSArray.

12

NSArray *myArray = [myNSSet allObjects];

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

zastąpić NSUInteger z indeksem żądanego obiektu.

+1

Powinna to być: MyObject * object = [myArray objectAtIndex: (NSUInteger *)] –

17

Możliwe jest użycie metody filtersSetUsingPredicate, jeśli masz jakiś unikalny identyfikator, aby wybrać potrzebny obiekt.

Najpierw utwórz predykat (zakładając swój unikalny identyfikator obiektu nazywa się „identyfikator” i jest NSString):

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

a następnie wybrać obiekt za pomocą predykatu:

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

Dla Swift3 & iOS10:

//your current set 
let mySet : NSSet 
//targetted index 
let index : Int 
//get object in set at index 
let object = mySet.allObjects[index] 
Powiązane problemy