95

如果你不能用 objectAtIndex: 从 NSSet 获取对象,那么你如何检索对象?

4

8 回答 8

142

一个集合有几个用例。您可以枚举(例如 withenumerateObjectsUsingBlock或 NSFastEnumeration),调用containsObject以测试成员资格,用于anyObject获取成员(非随机),或将其转换为数组(无特定顺序)allObjects

当您不想要重复、不关心顺序并想要快速的成员资格测试时,一组是合适的。

于 2010-09-30T00:12:17.393 回答
31

NSSet 没有方法 objectAtIndex:

尝试调用返回所有对象的 NSArray 的 allObjects。

于 2010-09-30T00:12:52.010 回答
17

如果您有某种唯一标识符来选择您需要的对象,则可以使用filteredSetUsingPredicate。

首先创建谓词(假设您在对象中的唯一 id 称为“标识符”并且它是一个 NSString):

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

然后使用谓词选择对象:

NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;
于 2013-08-04T14:20:01.067 回答
13

NSArray *myArray = [myNSSet allObjects];

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

将 NSUInteger 替换为所需对象的索引。

于 2013-03-04T06:20:07.220 回答
9

对于 Swift3 和 iOS10 :

//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]
于 2016-11-28T10:52:35.573 回答
6

NSSet 使用方法 isEqual: (您放入该集合的对象必须覆盖该方法,此外,hash 方法)来确定对象是否在其中。

因此,例如,如果您有一个通过 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
}

然后,您可以通过以下方式获取具有该 ID 的对象(以及检查它是否在 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 的原因之一。

于 2012-04-19T20:32:47.967 回答
0
for (id currentElement in mySet)
{
    // ** some actions with currentElement 
}
于 2016-06-20T21:31:25.267 回答
0

大多数时候,您并不关心从一组中获取一个特定对象。您关心测试以查看集合是否包含对象。这就是套装的好处。当您想查看一个对象是否在集合中时,集合比数组快得多。

如果你不关心你得到哪个对象,使用-anyObject它只会给你一个集合中的对象,例如将你的手放在袋子里并抓住一些东西。

Dog *aDog = [dogs anyObject]; // dogs is an NSSet of Dog objects

如果您关心得到什么对象,请使用-memberwhich 将对象返回给您,或者如果它不在集合中,则使用 nil。在调用它之前,您需要已经拥有该对象。

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);
}
于 2018-08-09T13:13:46.690 回答