我创建了简单的XCTest来测试distinctUnionOfObjects。除了isKindOfClass(Last XCTAssertTrue)之外,所有测试用例都通过了。知道为什么当你做distinctUnionOfObjects时它改变了类。
- (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");
}
答案 0 :(得分:3)
由于distinctUnionOfObjects
上的正确密钥路径为userName
,-valueForKeyPath
:调用将返回NSArray
个不同的用户名(不是用户对象)。
来自Apple的KVC Programming Guide:
@distinctUnionOfObjects运算符返回一个数组,该数组包含由运算符右侧的键路径指定的属性中的不同对象。
更改最后一个测试用例以检查[NSString class]
,它应该通过。
<强>替代强>
使用相等:
如果userName
属性应该作为唯一标识符,您可以通过覆盖用户对象上的-isEqual:
和-hash
来强制执行此操作,以反映这一点:
- (BOOL)isEqual:(id)object {
return ([object isKindOfClass:self.class] && [object.userName isEqual:self.userName]);
}
- (NSUInteger)hash {
return self.userName.hash;
}
这可以使您的整体模型设计受益,并开辟了许多其他选项,例如获取不同用户reg的集合。 userName在一行中 - NSSet
在用于此时非常快:
NSArray *uniqueUsers = [[NSSet setWithArray:users] allObjects];
NSString
的哈希函数作为用户哈希,这有一个微妙的陷阱; -[NSString hash]
仅保证最多96个字符的字符串的唯一性!这不在文档中,花了我差不多一天的时间来追踪生产代码。 (参见Apple的CFString.c实施 - 搜索__CFStrHashCharacters
)使用NSPredicate:
这是一个使用谓词的“创造性”解决方案。但是,需要进行某种迭代,因为谓词条件必须是其自身结果的函数:
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];
它获取一组唯一的userNames,对其进行迭代,为每个名称选择一个用户,并将其添加到输出数组中。
答案 1 :(得分:1)
你的测试毫无意义。您无法以这种方式使用distinct
因为@mvanellen
告诉您,您应该更改NSString
中的课程,因为您正在搜索不同的username
。
您反而尝试获取考虑不同用户名的对象列表,但这在概念上是错误的。如果需要,您应该尝试获取用户名列表,而不是整个对象的列表。
考虑进入你的阵列:
ITEM 1: aav / otherValue1
ITEM 2: aav / otherValue2
ITEM 3: matteo / otherValue3
肯定该函数会返回ITEM 3
,但是distinct
查询,ITEM 1
和ITEM 2
是否需要?
想一想;)