1

背景资料:

我编写了一个包含 2 个画廊的 iOS 应用程序:一个本地画廊和一个服务器画廊。当用户更新服务器图库并将其合并到他的本地图库时,应用程序应该只下载新图像。

ImageEntity为了最大限度地减少内存消耗,我保存图像并用具有以下属性的类的实例填充数组: fileNamefilePathvotingStatus

我尝试使用以下逻辑来检查图像是否已经存在:

for (ImageEntity *imageEntity in self.serverImagesArray) {
  if (![self.localImagesArray containsObject:imageEntity]){
    [self.localImagesArray  addObject:imageEntity];
  }
}

但是因为每个实体都是一个单独的对象,所以它总是会被添加。但是,每个实体都有一个唯一的文件名


问题: 我能否以某种方式扩展该[NSArray containsObject:]函数以检查数组中的一个对象是否具有等于“someValue”的属性?(当我将 Cocoa-Bindings 与 ArrayController 结合使用时,我可以分配数组元素的属性——我想访问与此类似的属性)。


我知道我可以使用将本地数组的每个实体与服务器数组上的每个元素进行比较不过,我必须进行 O(n^2) 比较,并且图库可能包含数百张图像。

额外的问题:我是否已经在没有意识到的情况下这样做了?有没有人有关于苹果实现这个功能的细节?是否有一些花哨的实现,或者他们只是在比较每个元素的数组上迭代?

4

2 回答 2

6

我这样做的方式是valueForKey:containsObject:. 因此,在您的情况下,您应该收集数组的所有文件名,然后检查数组是否包含您需要的特定文件名:

NSArray * fileNames = [fileEntityObjects valueForKey:@"fileName"];
BOOL contains = [fileNames containsObject:@"someFilename.jpg"];

fileName如果是fileEntityObjects数组中每个对象的属性,这将起作用。

更新

是的,您也可以这样做NSPredicate

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF.fileName = %@", "someFileName.jpg"];
NSArray * filteredArray = [fileEntityObjects filteredArrayUsingPredicate:predicate];

请注意,您将得到一个具有该文件名的对象数组,而不是布尔值。

于 2013-03-11T11:49:48.920 回答
1

由于这个问题被标记为“性能”,我添加了另一个答案:

为了避免 n^2 比较,我们必须找到一种更快的方法来检测已经存在的图像。为此,我们使用一个可以非常快速地执行查找的集合:

NSMutableSet *localFileNames = [NSMutableSet set];
for (ImageEntity *imageEntity in self.localImagesArray)
    [localFileNames addObject:imageEntity.fileName];

然后我们像以前一样遍历服务器图像。前一个containsObject:被快速集查找取代:

for (ImageEntity *imageEntity in self.serverImagesArray) {
    if ([localFileNames member:imageEntity.fileName] == nil)
        [self.localImagesArray addObject:imageEntity];
}
于 2013-03-11T13:44:52.020 回答