我已经坚持了很长一段时间了解问题: 我有两个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];
}
}
提前感谢任何提示;)
答案 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个值来唯一标识该对象。