从NSSet获取对象

nod*_*nja 92 cocoa cocoa-touch object objective-c nsset

如果你无法从一个NSSet中获取objectAtIndex的对象,那么如何检索对象呢?

Mat*_*hen 138

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

当您不想要重复,不关心订单以及想要快速成员资格测试时,一组是合适的.

  • 您还可以通过发送一个`member:`消息来查找潜在副本的已知对象.如果它返回`nil`,则该集合不包含与您传递的对象相等的对象; 如果它返回一个对象指针,那么它返回的指针就是该集合中已有的对象.集合中的对象必须实现`hash`和`isEqual:`才能使用. (7认同)
  • @ fumoboy007:对于存储在集合中或用作字典中的键,是的.从NSObject协议中的`hash`文档:"如果两个对象相等(由`isEqual:`方法确定),它们必须具有相同的哈希值."目前,NSObject的`hash`和`isEqual的实现:`使用对象的身份(地址).如果你重写`isEqual:`,你就设置了不相同但相等的对象的可能性 - 如果你不重写`hash`,它仍然会有不同的哈希值.这违反了相等对象具有相等哈希值的要求. (2认同)

No *_*lar 31

NSSet没有方法objectAtIndex:

尝试调用allObjects,它返回所有对象的NSArray.


Vit*_*lii 17

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

首先创建谓词(假设对象中的唯一id称为"标识符",它是一个NSString):

NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];
Run Code Online (Sandbox Code Playgroud)

然后使用谓词选择对象:

NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;
Run Code Online (Sandbox Code Playgroud)


kri*_*chu 13

NSArray *myArray = [myNSSet allObjects];

MyObject *object = [myArray objectAtIndex:(NSUInteger *)]
Run Code Online (Sandbox Code Playgroud)

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


Kev*_*OUX 8

对于Swift3和iOS10:

//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]
Run Code Online (Sandbox Code Playgroud)


hor*_*oe7 6

NSSet使用方法isEqual :(您放入该集合的对象必须覆盖哈希方法)以确定对象是否在其中.

因此,例如,如果您有一个数据模型,它通过id值定义其唯一性(比如属性是:

@property NSUInteger objectID;
Run Code Online (Sandbox Code Playgroud)

然后你实现isEqual:as

- (BOOL)isEqual:(id)object
{
  return (self.objectID == [object objectID]);
}
Run Code Online (Sandbox Code Playgroud)

你可以实现哈希:

- (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
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下内容获取具有该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
Run Code Online (Sandbox Code Playgroud)

但是,从NSSet中获取某些东西的唯一方法是首先考虑定义其唯一性的方法.

我没有测试过什么更快,但我避免使用枚举,因为这可能是线性的,而使用member:方法会快得多.这是优先使用NSSet而不是NSArray的原因之一.