Ios distinctUnionOfObjects不工作
我创建了简单的XCTest来测试distinctUnionOfObjects。所有的测试用例都通过了,除了一个是类的(最后一个是Xctasertrue)。你知道为什么在区分对象时会改变类吗Ios distinctUnionOfObjects不工作,ios,objective-c,nspredicate,distinct-values,Ios,Objective C,Nspredicate,Distinct Values,我创建了简单的XCTest来测试distinctUnionOfObjects。所有的测试用例都通过了,除了一个是类的(最后一个是Xctasertrue)。你知道为什么在区分对象时会改变类吗 - (void)testUsersPredicate { NSArray *usersBeforePredicate = [[self userData] users]; XCTAssertEqual([usersBeforePredicate count] , 34u,
- (void)testUsersPredicate
{
NSArray *usersBeforePredicate = [[self userData] users];
XCTAssertEqual([usersBeforePredicate count] , 34u, @"We need 34");
XCTAssertTrue([[usersBeforePredicate lastObject] isKindOfClass:[ICEUsersModelObject class]], @"Object is not ICEUsersModelObject class");
NSString *distinctUsersKeyPath = [NSString stringWithFormat:@"@distinctUnionOfObjects.%@", @"userName"];
NSArray* usersAfterPredicate = [usersBeforePredicate valueForKeyPath:distinctUsersKeyPath];
XCTAssertEqual([usersAfterPredicate count] , 30u, @"We need 30");
XCTAssertTrue([[usersAfterPredicate lastObject] isKindOfClass:[ICEUsersModelObject class]], @"Object is not ICEUsersModelObject class");
}
由于
distinctUnionOfObjects
上的右键路径是userName
,因此-valueForKeyPath
:调用将返回不同用户名的NSArray
来自苹果的:
@distinctUnionOfObjects操作符返回一个数组,该数组包含由操作符右侧的键路径指定的属性中的不同对象
将最后一个测试用例更改为检查[NSString class]
,它应该通过
备选方案
使用平等:
如果假定用户名
属性用作唯一标识符,则可以通过覆盖用户对象上的-isEqual:
和-hash
来强制执行该属性,以反映以下情况:
- (BOOL)isEqual:(id)object {
return ([object isKindOfClass:self.class] && [object.userName isEqual:self.userName]);
}
- (NSUInteger)hash {
return self.userName.hash;
}
这将有助于您的整体模型设计,并打开许多其他选项,例如此选项可获得不同用户的集合。一行中的用户名-NSSet
用于此项时速度非常快:
NSArray *uniqueUsers = [[NSSet setWithArray:users] allObjects];
- 注意:我对用户哈希重新使用了
的哈希函数,这有一个微妙的陷阱NSString
仅保证最多96个字符的字符串的唯一性!这不在文档中,我花了将近一天的时间在生产代码中找到它。(请参阅苹果的-search for-[NSString hash]
)\uu CFStrHashCharacters
NSMutableArray *__uniqueUsers = [NSMutableArray array];
[[users valueForKeyPath:@"@distinctUnionOfObjects.userName"] enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSArray *uniqueUser = [users filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id user, NSDictionary *bindings) {
return [user.userName isEqual:name];
}]];
if (uniqueUser.count > 0)
[__uniqueUsers addObject:uniqueUser.lastObject];
}];
NSArray *uniqueUsers = [NSArray arrayWithArray:__uniqueUsers];
它获取一组唯一用户名,对其进行迭代,为每个用户名选择一个用户,并将其添加到输出数组中。由于
distinctUnionOfObjects
上的右键路径是userName
,因此-valueForKeyPath
:调用将返回不同用户名的NSArray
(不是用户对象)
来自苹果的:
@distinctUnionOfObjects操作符返回一个数组,该数组包含由操作符右侧的键路径指定的属性中的不同对象
将最后一个测试用例更改为检查[NSString class]
,它应该通过
备选方案
使用平等:
如果假定用户名
属性用作唯一标识符,则可以通过覆盖用户对象上的-isEqual:
和-hash
来强制执行该属性,以反映以下情况:
- (BOOL)isEqual:(id)object {
return ([object isKindOfClass:self.class] && [object.userName isEqual:self.userName]);
}
- (NSUInteger)hash {
return self.userName.hash;
}
这将有助于您的整体模型设计,并打开许多其他选项,例如在一行中获得一组不同的用户注册用户名-NSSet
用于此功能时速度非常快:
NSArray *uniqueUsers = [[NSSet setWithArray:users] allObjects];
- 注意:我对用户哈希重新使用了
的哈希函数,这有一个微妙的陷阱;NSString
只保证最多96个字符的字符串的唯一性!这不在文档中,我花了将近一天的时间在生产代码中查找。(请参阅苹果的-search for-[NSString hash]
)\uu CFStrHashCharacters
NSMutableArray *__uniqueUsers = [NSMutableArray array];
[[users valueForKeyPath:@"@distinctUnionOfObjects.userName"] enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSArray *uniqueUser = [users filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id user, NSDictionary *bindings) {
return [user.userName isEqual:name];
}]];
if (uniqueUser.count > 0)
[__uniqueUsers addObject:uniqueUser.lastObject];
}];
NSArray *uniqueUsers = [NSArray arrayWithArray:__uniqueUsers];
它获取一组唯一的用户名,对其进行迭代,为每个用户名选择一个用户,并将其添加到输出数组中。您测试的用户名没有意义。您不能以这种方式使用
distinct
,因为正如@mvanellen
告诉您的那样,您应该更改NSString
中的类,因为您正在进行搜索g表示不同的用户名
相反,您尝试获取考虑了不同用户名的对象列表,但这在概念上是错误的。如果需要,您应该尝试获取用户名列表,而不是整个对象的列表
请考虑在阵列中包含:
ITEM 1: aav / otherValue1
ITEM 2: aav / otherValue2
ITEM 3: matteo / otherValue3
当然,该函数将返回项目3
,但作为一个不同的查询,应该从项目1
和项目2
中选择哪一个
想想看;)您测试的内容毫无意义。您不能以这种方式使用distinct
,因为正如@mvanellen
告诉您的那样,您应该更改NSString
中的类,因为您正在搜索distinct用户名
相反,您尝试获取考虑了不同用户名的对象列表,但这在概念上是错误的。如果需要,您应该尝试获取用户名列表,而不是整个对象的列表
请考虑在阵列中包含:
ITEM 1: aav / otherValue1
ITEM 2: aav / otherValue2
ITEM 3: matteo / otherValue3
当然,该函数将返回项目3
,但作为一个不同的查询,应该从项目1
和项目2
中选择哪一个
考虑一下;)谢谢你的回复。是的,我的想法在概念上是错误的。那么,“获取考虑不同用户名的对象列表”需要做什么呢。我可以使用NSPredicate吗?不可以。问题是这个。你不应该这么做。解释你的情况。你为什么需要这个?为了什么?如果函数返回的条目1或条目2除用户名外完全不同,那么这怎么可能不重要呢?谢谢您的回复。是的,我的想法在概念上是错误的。那么,“获取考虑不同用户名的对象列表”需要做什么呢。我可以使用NSPredicate吗?不可以。问题是这个。你不应该这么做。解释你的情况。你为什么需要这个?为了什么?这怎么可能不重要呢