Получение объекта из NSSet
Если вы не можете получить объект с objectAtIndex: из NSSet, то как вы получаете объекты?
8 ответов:
есть несколько вариантов использования набора. Вы можете перечислить через (например, с
enumerateObjectsUsingBlock
или NSFastEnumeration), звонитеcontainsObject
чтобы проверить членство, используйтеanyObject
чтобы получить член (не случайный), или преобразовать его в массив (в определенном порядке) сallObjects
.набор подходит, когда вы не хотите дубликатов, не заботитесь о порядке и хотите быстрого тестирования членства.
NSSet не имеет метода objectAtIndex:
попробуйте вызвать allObjects, который возвращает NSArray всех объектов.
можно использовать filteredSetUsingPredicate если у вас есть какой-то уникальный идентификатор, чтобы выбрать нужный объект.
сначала создайте предикат (предполагая, что ваш уникальный идентификатор в объекте называется "идентификатор" и это NSString):
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];
и затем выберите объект, используя предикат:
NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;
NSArray *myArray = [myNSSet allObjects];
MyObject *object = [myArray objectAtIndex:(NSUInteger *)]
замените NSUInteger на индекс нужного объекта.
NSSet использует метод isEqual: (который объекты, помещенные в этот набор, должны переопределить, кроме того, метод хэша), чтобы определить, находится ли объект внутри него.
так, например, если у вас есть модель данных, которая определяет ее уникальность по значению id (скажем, свойство:
@property NSUInteger objectID;
тогда вы бы реализовали isEqual: as
- (BOOL)isEqual:(id)object { return (self.objectID == [object objectID]); }
и вы могли бы реализовать хэш:
- (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 }
затем, вы можете получить объект с этим идентификатором (а также проверить для ли это в NSSet) с:
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
Но да, единственный способ получить что-то из NSSet это учитывая, что определяет его уникальность в первую очередь.
Я не проверял, что быстрее, но я избегаю использования перечисления, потому что это может быть линейным, тогда как использование метода member: было бы намного быстрее. Это одна из причин предпочесть использование NSSet вместо NSArray.
для Swift3 & iOS10:
//your current set let mySet : NSSet //targetted index let index : Int //get object in set at index let object = mySet.allObjects[index]
большую часть времени вы не заботитесь о получении одного конкретного объекта из набора. Вы заботитесь о тестировании, чтобы увидеть, содержит ли набор объект. Вот для чего хороши наборы. Если вы хотите увидеть, если объект находится в коллекции наборы намного быстрее, чем массивы.
если вы не заботитесь о , который объект вы получаете, используйте
-anyObject
который просто дает вам один объект из набора, например, положить руку в сумку и схватить что-то.Dog *aDog = [dogs anyObject]; // dogs is an NSSet of Dog objects
если вы заботьтесь о том, какой объект вы получаете, используйте
-member
который возвращает вам объект, или ноль, если он не находится в наборе. Вы должны уже иметь объект, прежде чем вызвать его.Dog *spot = [Dog dogWithName:@"Spot"]; // ... Dog *aDog = [dogs member:spot]; // Returns the same object as above
вот код, который вы можете запустить в Xcode, чтобы понять больше
NSString *one = @"One"; NSString *two = @"Two"; NSString *three = @"Three"; NSSet *set = [NSSet setWithObjects:one, two, three, nil]; // Can't use Objective-C literals to create a set. // Incompatible pointer types initializing 'NSSet *' with an expression of type 'NSArray *' // NSSet *set = @[one, two, three]; NSLog(@"Set: %@", set); // Prints looking just like an array but is actually not in any order //Set: {( // One, // Two, // Three // )} // Get a random object NSString *random = [set anyObject]; NSLog(@"Random: %@", random); // Random: One // Iterate through objects. Again, although it prints in order, the order is a lie for (NSString *aString in set) { NSLog(@"A String: %@", aString); } // Get an array from the set NSArray *array = [set allObjects]; NSLog(@"Array: %@", array); // Check for an object if ([set containsObject:two]) { NSLog(@"Set contains two"); } // Check whether a set contains an object and return that object if it does (nil if not) NSString *aTwo = [set member:two]; if (aTwo) { NSLog(@"Set contains: %@", aTwo); }