2013-05-05 3 views
1

이상한 동작을 보이는 핵심 데이터 백엔드가 있습니다. NSFetchRequest 내 응용 프로그램을 실행할 때 첫 번째 시간에 동일한 항목을 여러 번 주어진 경우에도 일치하는 항목을 찾지 못할 것입니다 ('결과가 없습니다'각 요청을 반환합니다 다음 데이터베이스에 중복 정보를 삽입하려면 진행 - 내가 내가 데이터베이스에 묶여 tableview가 있기 때문에 볼 수 있습니다).코어 데이터 : NSManagedObjectContext 저장되지 않음/가져 오기 요청이 실패 할 때까지 응용 프로그램 종료 및 다시 실행

홈 버튼을 눌러 앱을 종료 한 다음 앱을 다시 엽니 다. 예상대로 작동하기 시작합니다 (적절한 경우 결과가 반환 됨). 또한 앱을 삭제 한 다음 Xcode에서 다시 실행하여이 과정을 처음으로 다시 설정할 수 있습니다. NSManagedObjectContext (true를 반환합니다) 저장을 호출하는 경우에도 응용 프로그램이 닫힐 때까지 데이터베이스를 저장하지 않는 것 같습니다.

여기 무슨 일 이니? 이 작업을 예상대로 어떻게 수행합니까? NSManagedObjectContext에 대한 변경 사항을 저장하지 않고 있다고 생각하지만 어떻게해야합니까? 여기

이 가져 오는 함수의/반환 내 NSManagedObjectContext에서 객체 :

+ (Mark *)markWithTWLInfo:(NSDictionary *)markDictionary 
    inManagedObjectContext:(NSManagedObjectContext *)context 
{ 
    Mark *mark = nil; 

    NSLog(@"Starting Operation for Key: %@", [markDictionary[JS_MARK_ID] description]); 

    // Build a fetch request to see if we can find this Mark in the database. 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Mark"]; 
    request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]]; 
    request.predicate = [NSPredicate predicateWithFormat:@"idUnique = %@", [markDictionary[JS_MARK_ID] description]]; 

    // Execute the fetch 

    NSError *error = nil; 
    NSArray *matches = [context executeFetchRequest:request error:&error]; 

    // Check what happened in the fetch 

    if (!matches || ([matches count] > 1) || error) { // nil means fetch failed; more than one impossible (unique!) 
     // handle error 
     if (error) { 
      NSLog(@"Fetch error: %@", [error description]); 
     } else { 
      NSLog(@"Found No/Multiple matches for key: %@", [markDictionary[JS_MARK_ID] description]); 
     } 
    } else if (![matches count]) { // none found, so let's create a mark 

     NSLog(@"Inserting: %@", [markDictionary[JS_MARK_ID] description]); 

     mark = [NSEntityDescription insertNewObjectForEntityForName:@"Mark" inManagedObjectContext:context]; 
     mark.idUnique = [NSNumber numberWithInt:[markDictionary[JS_MARK_ID] intValue]]; 

     //Save the changes; this returns True 
     if ([context save:&error]) { 
      NSLog(@"Saved is true"); 
     } else { 
      NSLog(@"Saved is false"); 
     } 

     if (error) { 
      NSLog(@"Save error: %@", [error description]); 
     } 
    } else { // found the mark, just return it from the list of matches (which there will only be one of) 
     NSLog(@"Found existing object for key: %@", [markDictionary[JS_MARK_ID] description]); 
     mark = [matches lastObject]; 
    } 
    return mark; 
} 

는 내가 삽입 할 모든 마크과 같이이 함수를 호출 :

다음
for (NSDictionary *mark in results) { 
    if (DEMO_LOGGING) NSLog(@"Inserting: %@",[mark objectForKey:@"Mark"]); 
    [self.managedObjectContext performBlock:^{ 
     [Mark markWithTWLInfo:[mark objectForKey:@"Mark"] inManagedObjectContext:self.managedObjectContext]; 
    }]; 
} 

내가 볼거야 이 문제가 발생하면 로그에 다음을 입력하십시오.

- 새로운 데이터베이스로 앱 시작 :

2013-05-05 16:45:08.105 ToWatchList[10155:c07] Starting Operation for Key: 731 
2013-05-05 16:45:08.106 ToWatchList[10155:c07] Inserting: 731 
2013-05-05 16:45:08.111 ToWatchList[10155:c07] Saved is true 
2013-05-05 16:45:10.651 ToWatchList[10155:c07] Starting Operation for Key: 731 
2013-05-05 16:45:10.652 ToWatchList[10155:c07] Inserting: 731 
2013-05-05 16:45:10.654 ToWatchList[10155:c07] Saved is true 

-QUIT 예상대로 여기

2013-05-05 16:45:29.816 ToWatchList[10155:c07] Starting Operation for Key: 731 
2013-05-05 16:45:29.817 ToWatchList[10155:c07] Found No/Multiple matches for key: 731 

- 이제 NSFetchRequest 내 2 개 이전 항목을 반환 프로그램을 다시 시작하지만 두 번째를 삽입하려고 할 때 그것은 첫 번째를 볼 수 있어야합니다.

답변

4

내 생각에 부모의 컨텍스트는 self.managedObjectContext입니다.

이 경우 속성의 고유성을 보장하려면 스토어에 모든 것을 저장해야합니다 (parentContext이 존재할 때까지 재귀 적으로 저장해야 함).

고유성을 보장하려면 모든 상위 컨텍스트에서 저장이 완료 될 때까지 기다려야합니다.

교체하여 [context save:&error]과 :

NSManagedObjectContext* c = context; 
__block BOOL success = YES; 
while (c && success) { 
    [c performBlockAndWait:^{ 
     success = [c save:&error]; 
     //handle save success/failure 
    }]; 
    c = c.parentContext; 
} 
+0

예, 이건 내 문제가 있었다, 나는 같은 스레딩 함께 할 수있는 뭔가했지만 그것을 해결하는 방법을 모르는 것이라고 상상했다. 또한, 컴파일러가 불평을 피하기 위해 블록 내에서 새로운 NSError 변수를 선언하고 인스턴스화해야했습니다 :'NSError * blockError = Nil;'(나는 이것을 게시물의 편집으로 추가하려했으나 거부되었습니다. :-() – Nick

+0

추가적으로'error' 객체가 필요 없으며'__block NSError * error = nil;'으로 선언 한 것만으로도 기꺼이 도와 드리겠습니다. –

+0

그래, Nil로 설정하려고했는데 효과가 있었다. 너무 ...하지만 오히려 뭔가 잘못 될 경우 오류를 기록하고 싶습니다. – Nick