Wenn Sie mit objectAtIndex kein Objekt erhalten können: Von einem NSSet, wie rufen Sie dann Objekte ab?Abrufen eines Objekts von einem NSSet
Antwort
Es gibt mehrere Anwendungsfälle für ein Set. Sie könnten durchnummerieren (z. B. mit enumerateObjectsUsingBlock
oder NSFastEnumeration), containsObject
anrufen, um auf Mitgliedschaft zu testen, anyObject
verwenden, um ein Mitglied (nicht zufällig) zu erhalten, oder es in ein Array (in keiner bestimmten Reihenfolge) mit allObjects
konvertieren.
Ein Satz ist geeignet, wenn Duplikate vermieden werden sollen, die Reihenfolge nicht wichtig ist und schnelle Mitgliedschaftstests gewünscht werden.
NSSet haben keine Methode objectAtIndex:
Aufruf allObjects Versuchen Sie, die eine NSArray aller Objekte zurückgibt.
Haben Sie eine Idee, ob das zurückgegebene Array bestellt wurde? Mit anderen Worten, wenn das Hinzufügen von Objekten zum Set mit "setByAddingObject" und ich "allObjects" verwendet, sind? die Elemente in der Anordnung geordnet in der Reihenfolge, in der ich die Objekte hinzugefügt habe? – iosMentalist
Sortieren Sie das resultierende Array einfach mit einem NSSortPredicate und Sie werden in Ordnung sein. – Jason
Wenn Sie nur an einem bestimmten Objekt interessiert sind, verwenden Sie besser den filteredSetUsingPredicate-Ansatz. – akw
NSSet verwendet die Methode isEqual: (die Objekte, die Sie in diesen Satz einfügen, müssen zusätzlich die Hash-Methode überschreiben), um festzustellen, ob ein Objekt darin enthalten ist.
So zum Beispiel, wenn Sie ein Datenmodell haben, das die Einzigartigkeit durch einen ID-Wert definiert (zB die Eigenschaft:
@property NSUInteger objectID;
dann würden Sie isEqual implementieren: als
- (BOOL)isEqual:(id)object
{
return (self.objectID == [object objectID]);
}
und Sie könnten 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
}
dann können Sie ein Objekt mit dieser ID (sowie für überprüfen für ob es in der NSSet) ist mit:
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
Aber ja, die einzige Möglichkeit, etwas aus einem NSSet zu erhalten ist, indem man bedenkt, dass das seine Einzigartigkeit in erster Linie definiert.
Ich habe nicht getestet, was schneller ist, aber ich vermeide die Verwendung von Enumeration, weil das linear sein könnte, während die Verwendung der Methode Mitglied: wäre viel schneller. Das ist einer der Gründe, die Verwendung von NSSet anstelle von NSArray zu bevorzugen.
NSArray *myArray = [myNSSet allObjects];
MyObject *object = [myArray objectAtIndex:(NSUInteger *)]
ersetzen NSUInteger mit dem Index des gewünschten Objekts.
Sollte sein: MyObject * object = [myArray objectAtIndex: (NSUInteger *)] –
Es ist möglich, filteredSetUsingPredicate zu verwenden, wenn Sie eine eindeutige Kennung haben, um das gewünschte Objekt auszuwählen.
Zuerst das Prädikat erstellen (Ihre eindeutige ID im Objekt angenommen wird „Kennung“ genannt, und es ist ein NSString):
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];
Und dann wählen Sie das Objekt mit dem Prädikat:
NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;
for (id currentElement in mySet)
{
// ** some actions with currentElement
}
Für swift3 & iOS10:
//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]
Sie können ein bekanntes Objekt auch nach einem möglichen Duplikat suchen, indem Sie der Gruppe eine 'member:' Nachricht senden. Wenn es "Null" zurückgibt, enthält die Menge kein Objekt, das dem übergebenen entspricht. Wenn es einen Objektzeiger zurückgibt, ist der zurückgegebene Zeiger auf das Objekt, das bereits in der Menge ist. Die Objekte in der Menge müssen 'hash' und' isEqual: 'implementieren, damit dies nützlich ist. –
@PeterHosey Ich glaube nicht, dass 'hash' _needs_ implementiert werden muss; es würde einfach viel schneller gehen, wenn Sie das tun würden. – fumoboy007
@ fumoboy007: Für die Speicherung in einem Satz oder als Schlüssel in einem Wörterbuch, ja, tut es. Aus der Dokumentation von "hash" im NSObject-Protokoll: "Wenn zwei Objekte gleich sind (wie durch die' isEqual: '-Methode bestimmt), müssen sie den gleichen Hash-Wert haben." Derzeit implementiert NSObject 'hash' und' isEqual : 'Verwenden Sie die Identität des Objekts (Adresse). Wenn Sie 'isEqual:' überschreiben, richten Sie die Möglichkeit ein, dass Objekte, die nicht identisch sind, aber gleich sind - was, wenn Sie nicht auch 'hash' überschreiben, immer noch verschiedene Hashes haben. Dies verletzt die Anforderung, dass gleiche Objekte gleiche Hashes haben. –