Получение объекта из NSSet


Если вы не можете получить объект с objectAtIndex: из NSSet, то как вы получаете объекты?

8 88

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]
for (id currentElement in mySet)
{
    // ** some actions with currentElement 
}

большую часть времени вы не заботитесь о получении одного конкретного объекта из набора. Вы заботитесь о тестировании, чтобы увидеть, содержит ли набор объект. Вот для чего хороши наборы. Если вы хотите увидеть, если объект находится в коллекции наборы намного быстрее, чем массивы.

если вы не заботитесь о , который объект вы получаете, используйте -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);
}