[英]Check two NSArrays for containing each other's objects (NSManagedObject)
現在,我在以下問題上停留了很長時間:我有兩個NSArray,都包含NSManagedObject子類對象。 它們由不同的來源提供,但是其中的對象仍然具有相同的屬性/值。 我現在想做的是檢查數組A是否包含來自數組B的對象,反之亦然。 不幸的是,NSArray的containsObject方法似乎在這里不起作用。 我認為它對每個對象的相等性檢查使用id測試,不是嗎?
那么,有人有線索,該怎么辦?
我什至嘗試使用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];
}
}
預先感謝您的任何提示;)
我不確定這是否可行,但是您可以嘗試將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:
方法並手動枚舉數組。
您可以檢查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];
}
}
您需要重寫-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個值即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.