Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/115.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios distinctUnionOfObjects不工作_Ios_Objective C_Nspredicate_Distinct Values - Fatal编程技术网

Ios distinctUnionOfObjects不工作

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,

我创建了简单的XCTest来测试distinctUnionOfObjects。所有的测试用例都通过了,除了一个是类的(最后一个是Xctasertrue)。你知道为什么在区分对象时会改变类吗

- (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
    的哈希函数,这有一个微妙的陷阱
    -[NSString hash]
    仅保证最多96个字符的字符串的唯一性!这不在文档中,我花了将近一天的时间在生产代码中找到它。(请参阅苹果的-search for
    \uu 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];

它获取一组唯一用户名,对其进行迭代,为每个用户名选择一个用户,并将其添加到输出数组中。

由于
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
    的哈希函数,这有一个微妙的陷阱;
    -[NSString hash]
    只保证最多96个字符的字符串的唯一性!这不在文档中,我花了将近一天的时间在生产代码中查找。(请参阅苹果的-search for
    \uu 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];

它获取一组唯一的用户名,对其进行迭代,为每个用户名选择一个用户,并将其添加到输出数组中。

您测试的用户名没有意义。您不能以这种方式使用
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吗?不可以。问题是这个。你不应该这么做。解释你的情况。你为什么需要这个?为了什么?这怎么可能不重要呢