如果你不能用 objectAtIndex: 从 NSSet 获取对象,那么你如何检索对象?
8 回答
一个集合有几个用例。您可以枚举(例如 withenumerateObjectsUsingBlock
或 NSFastEnumeration),调用containsObject
以测试成员资格,用于anyObject
获取成员(非随机),或将其转换为数组(无特定顺序)allObjects
。
当您不想要重复、不关心顺序并想要快速的成员资格测试时,一组是合适的。
NSSet 没有方法 objectAtIndex:
尝试调用返回所有对象的 NSArray 的 allObjects。
如果您有某种唯一标识符来选择您需要的对象,则可以使用filteredSetUsingPredicate。
首先创建谓词(假设您在对象中的唯一 id 称为“标识符”并且它是一个 NSString):
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];
然后使用谓词选择对象:
NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;
NSArray *myArray = [myNSSet allObjects];
MyObject *object = [myArray objectAtIndex:(NSUInteger *)]
将 NSUInteger 替换为所需对象的索引。
对于 Swift3 和 iOS10 :
//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]
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 的原因之一。
for (id currentElement in mySet)
{
// ** some actions with currentElement
}
大多数时候,您并不关心从一组中获取一个特定对象。您关心测试以查看集合是否包含对象。这就是套装的好处。当您想查看一个对象是否在集合中时,集合比数组快得多。
如果你不关心你得到哪个对象,使用-anyObject
它只会给你一个集合中的对象,例如将你的手放在袋子里并抓住一些东西。
Dog *aDog = [dogs anyObject]; // dogs is an NSSet of Dog objects
如果您关心得到什么对象,请使用-member
which 将对象返回给您,或者如果它不在集合中,则使用 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);
}