2012-02-14 49 views
0

我被困在以下问题相当一段时间了: 我有两个NSArrays,都包含NSManagedObject子类对象。 它们由不同的来源提供,但其中的对象仍具有相同的属性/值。 我现在想要做的是检查数组A是否包含数组B中的对象,反之亦然。 不幸的是NSArray的containsObject方法在这里似乎不起作用。 我认为它在每个对象上使用了id-testing进行相等性检查,不是吗?检查两个NSArrays包含对方的对象(NSManagedObject)

那么,有没有人有线索,要尝试什么?

我甚至试图将我的对象封装在NSSets中,使用成员:作为我的比较方法,但这并没有解决,尤其是因为“你不能重写”isEqual等NSManagedObject子类。

这里有一个代码片段:

//manufacturers is an array, parsed out of some xml here... 

for(Manufacturer *manu in [fetchedResultsController fetchedObjects]) 
{ 
    if(![manufacturers containsObject:manu]) 
    { 
     NSLog(@"Deleting %@", manu.name); 
     [self.mContext deleteObject:manu]; 
    } 
} 

for(Manufacturer *manu in manufacturers) 
{ 
    if(![[fetchedResultsController fetchedObjects] containsObject:manu]) 
    { 
     NSLog(@"Adding %@", manu.name); 
     [newArray addObject:manu]; 
    } 
} 

预先感谢任何暗示;)

回答

0

我不知道,如果这个工程,但你可以尝试匹配你dictionaryWithValuesForKeys:得到的字典。

事情是这样的:

NSArray *keysToCompare = [NSArray arrayWithObjects:@"FooAttribute", @"BarAttribute", nil]; 

// create an array with the dictionary representation of the managedObject 
NSMutableArray *fetchedObjectsDictionaries = [NSMutableArray arrayWithCapacity:[[fetchedResultsController fetchedObjects] count]]; 
for (NSManagedObject *object in [fetchedResultsController fetchedObjects]) { 
    NSDictionary *dictionaryRepresentation = [object dictionaryWithValuesForKeys:keysToCompare]; 
    [fetchedObjectsDictionaries addObject:dictionaryRepresentation]; 
} 

// another array with dictionaries for managedObjects 
NSMutableArray *manufacturersDictionaries = [NSMutableArray arrayWithCapacity:[manufacturers count]]; 
for (NSManagedObject *object in manufacturers) { 
    NSDictionary *dictionaryRepresentation = [object dictionaryWithValuesForKeys:keysToCompare]; 
    [manufacturersDictionaries addObject:dictionaryRepresentation]; 
} 

// compare those dictionaries 
for (NSInteger i = 0; i < [fetchedObjectsDictionaries count]; i++) { 
    NSDictionary *dictionary = [fetchedObjectsDictionaries objectAtIndex:i]; 
    if (![manufacturersDictionaries containsObject:dictionary]) { 
     // get the corresponding managedObject 
     NSManagedObject *object = [[fetchedResultsController fetchedObjects] objectAtIndex:i]; 
     [newArray addObject:object]; 
    } 
} 

如果这是行不通的,你可以写自己的isEqualToManufacturer:方法,并列举手动槽的阵列。

+0

如果这些数组包含多个对象,则这非常昂贵并且速度很慢。 – 2012-02-15 08:29:09

0

可以检查3种类型的相等:相同的内存地址,托管对象ID相等和值相等。您当前的代码已经检查,看看对象是否共享相同的内存地址,这很可能不是您感兴趣的内容。这留下了两种可能的选择。使用托管对象ID相等方法,您可以检查制造商是否指向数据库中的同一行。使用值相等性,您可以根据共享值检查两个制造商是否相等。下面是一个检查NSManagedObjectID相等性的方法。

for(Manufacturer *manu in [fetchedResultsController fetchedObjects]) 
{ 
    id databaseIDTest = ^(Manufacturer * checkManu, NSUInteger idx, BOOL *stop){ 
     return [[checkManu objectID] isEqual:[manu objectID]]; 
    }; 

    if([manufacturers indexOfObjectPassingTest:databaseIDTest] == NSIndexNotFound) 
    { 
     NSLog(@"Deleting %@", manu.name); 
     [self.mContext deleteObject:manu]; 
    } 
} 

for(Manufacturer *manu in manufacturers) 
{ 
    id databaseIDTest = ^(Manufacturer * checkManu, NSUInteger idx, BOOL *stop){ 
     return [[checkManu objectID] isEqual:[manu objectID]]; 
    }; 
    NSArray * fetchedObjects = [fetchedResultsController fetchedObjects]; 
    if([fetchedObjects indexOfObjectPassingTest:databaseIDTest] == NSIndexNotFound) 
    { 
     NSLog(@"Adding %@", manu.name); 
     [newArray addObject:manu]; 
    } 
} 
+0

这不完全正确。既然你处于同一个上下文中,比较两个指针(内存地址)和比较两个管理对象ID有效地做同样的事情,但比较两个指针是一个**很便宜(数量级)。 – 2012-02-15 08:21:42

+0

非常感谢您的回答,但这似乎并不奏效...想想我可能需要手动迭代我的数组并计算出现次数。至少这是我能想到的唯一方法来测试物体“我的方式”。 – Revoluzifer 2012-02-15 09:06:51

-2

你需要重写-isEqual:,因为这就是-[NSArray containsObject:]调用到:

- (BOOL)isEqual:(id)other; 
{ 
    if (![other isKindOfClass:[Manufacturer class]]) { 
     return NO; 
    } 
    Manufacturer *otherManufacturer = other; 
    return ([self.name isEqual:otherManufacturer.name] && 
      ... 
      ); 
} 

检查的NSSet中内遏制是便宜(和可能是有意义的,如果你遇到性能问题)。它只有当你有一个相对体面的-hash实施工作,但可以很容易地实现这样的:

- (NSUInteger)hash; 
{ 
    return [self.name hash] + [self.foo hash] + ...; 
} 

不要走线槽太麻烦与哈希,只需使用2 - 3值是最有可能来唯一标识对象。

+0

我希望能够简单地重写我的对象的比较方法,但由于我使用的NSManagedObject子类我不能。否则,这肯定是最好的解决方案;) – Revoluzifer 2012-02-15 08:52:44