检查两个NSArrays以包含彼此的对象(NSManagedObject)

时间:2012-02-14 16:12:11

标签: iphone objective-c ios core-data

我已经坚持了很长一段时间了解问题: 我有两个NSArrays,都包含NSManagedObject子类对象。 它们由不同的源提供,但它们中的对象仍然具有相同的属性/值。 我现在要做的是检查数组A是否包含来自数组B的对象,反之亦然。 不幸的是,NSArray的containsObject-method似乎在这里不起作用。 我认为它使用id-testing对每个对象进行相等性检查,不是吗?

那么,有没有人知道该怎么办?

我甚至尝试使用member:作为我的比较方法将我的对象封装在NSSets中,但是这也没有用,特别是因为“你不能覆盖”对于NSManagedObject子类的isEqual等。

以下是代码段:

//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];
    }
}

提前感谢任何提示;)

3 个答案:

答案 0 :(得分: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:方法并手动枚举数组。

答案 1 :(得分: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];
    }
}

答案 2 :(得分:-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个值来唯一标识该对象。