簡體   English   中英

檢查兩個NSArray是否包含彼此的對象(NSManagedObject)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM