背景资料:
我编写了一个包含2个图库的iOS应用程序:本地图库和服务器库。当用户更新服务器库并将其合并到本地服务器库时,应用程序应该只下载新图像。
为了最大程度地减少内存消耗,我保存了图像,并使用以下属性填充了ImageEntity
类的实例: fileName , filePath &的 votingStatus
我尝试使用以下逻辑来检查图像是否已存在:
for (ImageEntity *imageEntity in self.serverImagesArray) {
if (![self.localImagesArray containsObject:imageEntity]){
[self.localImagesArray addObject:imageEntity];
}
}
但是因为每个实体都是一个单独的对象,所以它总是被添加。每个实体都有一个唯一的 fileName 。
问题:
我可以以某种方式扩展[NSArray containsObject:]
函数来检查数组中的一个对象是否具有等于“someValue”的属性? (当我将Cocoa-Bindings与ArrayController结合使用时,我可以分配数组元素的属性 - 我想访问与此类似的属性。)
我知道我可以使用比较本地数组的每个实体与服务器阵列上的每个元素。 我必须进行O(n ^ 2)比较,但画廊可能包含数百张图片。
奖金问题:我是否已经意识到这一点?有没有人有关于Apple实现此功能的详细信息?是否有一些奇特的实现,或者他们只是在比较每个元素时迭代数组?
答案 0 :(得分:5)
我这样做是将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];
请注意,不是布尔值,而是获得具有该文件名的对象数组。
答案 1 :(得分: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];
}