2012-02-14 1 views
0

꽤 많은 시간 동안 다음과 같은 문제에 봉착했습니다. NSManagedObject 하위 클래스 객체를 포함하는 두 개의 NSArrays가 있습니다. 그들은 다른 출처에 의해 먹이를 먹었지 만 그 안의 개체는 여전히 동일한 속성/값을 가지고 있습니다. 지금하고 싶은 것은 배열 A에 배열 B의 객체가 포함되어 있는지, 아니면 그 반대인지를 확인하는 것입니다. 아쉽게도 NSArray의 containsObject-method가 여기에서 작동하지 않습니다. 각 객체의 동일성 검사에 ID 테스트를 사용한다고 생각합니까?서로의 객체 (NSManagedObject)를 포함하는 두 개의 NSArrays를 확인하십시오.

그럼, 아무도 실마리를 가지고 있습니까?

내 비교 방법으로 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

이 작동하는지 잘 모르겠어요,하지만 당신은 당신이 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

이러한 배열에 개체가 두 개 이상 있으면 매우 비싸고 속도가 느립니다. –

0

확인할 수있는 동일한 메모리 주소, 관리되는 개체 ID 평등 및 값 평등의 세 가지 유형이 있습니다. 현재 코드는 객체가 동일한 메모리 주소를 공유하는지 여부를 이미 확인합니다. 이는 관심이없는 것일 가능성이 큽니다. 두 가지 옵션이 있습니다. 관리 대상 객체 id 평등 방법을 사용하면 제조업체가 데이터베이스의 동일한 행을 가리키는 지 확인할 수 있습니다. 가치 평등을 사용하면 두 제조업체가 공유 값을 기준으로 동등한 지 확인할 수 있습니다. 아래는 NSManagedObjectID 동등성을 검사하는 방법입니다. NSSet 내부에 포함되어 있는지 확인

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

저렴 (당신은 성능 문제로 실행하면 의미가 있음) :

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를 비교하는 것이 동일한 작업을 수행하지만 두 포인터를 비교하는 것은 ** 많은 ** 비용이 저렴합니다. –

+0

답장을 보내 주셔서 감사합니다.하지만이 방법이 효과가없는 것 같습니다. 배열을 반복하여 반복적으로 계산해야 할 수도 있습니다.적어도 이것이 "내 방식"의 객체를 테스트 할 수있는 유일한 방법입니다. – Revoluzifer

-2

당신은이에 -[NSArray containsObject:] 호출은 무엇 때문에 -isEqual:를 오버라이드 (override) 할 필요가있다. 당신이 상대적으로 괜찮은 -hash 구현을 경우에만 작동하지만, 이렇게 쉽게 구현할 수 :

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

단지 2 개를 사용, 해시로 저점 너무 많은 문제를 이동하지 마십시오

- 가능성이 가장 높은 3 값을은 개체를 고유하게 식별합니다.

+0

난 내 개체의 비교 메서드를 단순히 재정의 할 수 있지만 NSManagedObject 하위 클래스를 사용할 수 있기를 원합니다. 그렇지 않으면 이것이 가장 좋은 해결책이었을 것입니다.) – Revoluzifer

관련 문제