핵심 데이터 패턴 : 네트워크에서 변경하여 로컬 정보를 효율적으로 업데이트하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/2209228

문제

이해하고 고치고 싶은 앱에 약간의 비 효율성이 있습니다.

내 알고리즘은 다음과 같습니다.

fetch object collection from network
for each object:
  if (corresponding locally stored object not found): -- A
    create object
    if (a nested related object locally not found): -- B
      create a related object

내 스키마의 일부인 관련 객체의 키로 술어 쿼리를 만들어 라인 A와 B에 대한 검사를 수행하고 있습니다. 나는 A (항상)와 B (실행이 해당 부품에 분기 된 경우)가 모두 SQL Select를 생성한다는 것을 알 수 있습니다.

2010-02-05 01:57:51.092 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE1 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.097 app[393:207] CoreData: annotation: sql connection fetch time: 0.0046s
2010-02-05 01:57:51.100 app[393:207] CoreData: annotation: total fetch execution time: 0.0074s for 0 rows.
2010-02-05 01:57:51.125 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE2 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.129 app[393:207] CoreData: annotation: sql connection fetch time: 0.0040s
2010-02-05 01:57:51.132 app[393:207] CoreData: annotation: total fetch execution time: 0.0071s for 0 rows.

쿼리의 경우 0.0071은 3GS 장치에서는 괜찮지 만 100 개를 추가하면 700ms 차단기가 있습니다.

내 코드에서 나는 이력서를 사용하여 다음을 수행합니다.

- (MyObject *) myObjectById:(NSNumber *)myObjectId {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[self objectEntity]]; // my entity cache    
    [fetchRequest setPredicate:[self objectPredicateById:objectId]]; // predicate cache    
    NSError *error = nil;
    NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count] == 1) {
        [fetchRequest release];
        return [fetchedObjects objectAtIndex:0];
    }
    [fetchRequest release];
    return nil;
}

MyObject *obj = [self myObjectById];
if (!obj) {
   // [NSEntityDescription insertNewObjectForEntityForName: ... etc
}

나는 이것이 잘못되었다고 생각하고 다른 방법으로 점검해야합니다. 데이터베이스에 한 번만 누르면 메모리에서 나와야합니다. (SQL은 내가 알고있는 객체에 대해서도 로컬로 존재하고 이전 쿼리를 사용하여 메모리에로드되었을 것입니다.) 그러나 외부 소스에서 myObjectId 만있는 경우 이것이 내가 생각할 수있는 최선입니다.

따라서 질문은 아마도 다음과 같습니다. myObjectID (myObject의 핵심 데이터 int64 속성)가 있다면 CD 스토어에 관련 로컬 객체가 존재하는지 어떻게 올바르게 확인해야합니까? 가능한 일치의 전체 세트를 사전로드 한 다음 로컬 어레이를 식별합니까?

(한 가지 가능한 솔루션은 이것을 배경 스레드로 옮기는 것입니다. 스레드에서 변경을받을 때 [Moc MergechangesfromContextDidSavenotification : ANotification]; 여전히 차단됩니다.)

도움이 되었습니까?

해결책

Core Data Programming Guide에서 "Find-Or-Create를 효율적으로 구현"하십시오.

기본적으로 이름과 같은 ID 또는 속성 배열 또는 관리되는 객체 엔티티에서 가지고있는 모든 것을 만들어야합니다.

그런 다음이 배열을 사용하여 관리되는 객체를 필터링하는 술어를 만들어야합니다.

[fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(objectID IN %@)", objectIDs]];

물론 "Objectids"는 식별하는 데 사용할 수있는 모든 것일 수 있습니다. nsmanagedobjectid 일 필요는 없습니다.

그런 다음 하나의 가져 오기 요청을 수행하고 결과적인 객체를 반복하여 복제물을 찾을 수 있습니다. 존재하지 않으면 새 것을 추가하십시오.

다른 팁

아마도 이메일 클라이언트로부터 교훈을 얻을 수 있습니다.

먼저 메시지 ID 목록에 대해 서버를 쿼리하여 작동합니다. 클라이언트가 해당 목록을 가지고 있으면 로컬 데이터 저장소와 비교하여 다른 것이 있는지 확인합니다.

차이가 있으면 몇 가지 행동 중 하나가 필요합니다. 1. 클라이언트에 존재하지만 서버가 아닌 경우 IMAP 인 경우 로컬로 삭제하십시오. 2. 클라이언트가 아닌 서버에 존재하는 경우 나머지 메시지를 다운로드하십시오.

귀하의 경우 모든 ID에 대한 첫 번째 쿼리. 그런 다음 후속 쿼리를 보내서 아직 보유하지 않은 데이터에 대한 모든 데이터를 가져옵니다.

레코드가 로컬로 존재하지만 서버에서 마지막 다운로드 이후 업데이트 된 상황이있는 경우 쿼리에는 마지막 업데이트 된 날짜가 포함되어야합니다.

모든 객체를 가로 질러 가져와야하지만 객체의 서버 ID 만 가져와야합니다.

사용 setProperTiestOtchetch : ~와 함께 setResultType : 로 설정 NSDictionaryResultType.

그것은 당신이 필요로하는 것이 nsmanagedobjectids의 nsset 인 것처럼 들리며, 이는 메모리에로드되거나 지속적인 객체 저장소보다 더 빠르게 액세스 할 수있는 곳에 저장됩니다.

이렇게하면 큰 데이터 세트에서 페치 요청을 수행하지 않고도 캐시의 객체 ID와 네트워크의 객체 ID를 비교할 수 있습니다.

관리 된 엔티티 클래스 내에서 -awakefrominsert 내에서 캐시에 ID를 추가 할 수 있습니까?

오랜 세월 동안이 같은 문제와 싸우고 나서 마침내이 블로그 항목을 우연히 발견했습니다.

http://henrik.nyh.se/2007/01/importing-legacy-data-into-core-data-with-to-find-or-create 또는 delete-pattern

코드 샘플은 네트워크 부분을 다루지 않습니다. 당신은 단순히 그것을 nsdictionary에로드하면됩니다. 그리고 이것은 로컬 핵심 데이터 컨텍스트의 동기화를 다룹니다.

답변이 아니라 "효율적으로 데이터 가져 오기"문서에 대한 업데이트 된 URL

http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/coredata/articles/cdimporting.html#//apple_ref/doc/uid/tp40003174-sw1

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top