2014-01-20 3 views
0

코어 데이터가 백그라운드 스레드에서 작동하는 것을 이해하는 데는 여전히 어려움이 있습니다. 특히 객체 삭제와 관련하여 많은 것을 읽은 후에도 어려움이 있습니다. 예를 들어코어 데이터 객체 삭제 및 백그라운드 스레드 저장

,이 같은 맥락에서 개체를 삭제하려면 :

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObjectContext *context = [self managedObjectContext]; 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     // Delete object from database 
     [context deleteObject:[self.tests objectAtIndex:indexPath.row]]; 
     NSError *error = nil; 
     if (![context save:&error]) { 
      NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]); 
      return; 
     } 
     [self.tests removeObjectAtIndex:indexPath.row]; 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

이 작동하지만 데이터가 큰 경우, [context save:&error] 시간이 많이 걸립니다, 그래서 내가 어떻게 할 수 백그라운드에서? 다른 컨텍스트에서 작업 할 수없는 것 같습니다. 그렇지 않으면 오류 an nsmanagedobjectcontext cannot delete objects in other contexts이 표시됩니다. 나는 수백 가지 다른 것들을 시도했지만 잃어버린 ... 고마워!

답변

0

NSManagedObjectContext에서 performBlock 및 performBlockAndWait 메서드를 살펴보십시오.

정확히이 상황을 피하기 때문에 내 UI 바인딩 된 관리 된 개체 컨텍스트에 대해서도 NSPrivateQueueConcurrencyType을 사용하는 것이 좋습니다. 예를 들어, 당신은 이런 식으로 뭔가를 할 수 : 상황에 맞는 별도의 스레드에서 바쁜 절약 그대로있는 tableView 업데이트를 진행 할 수 있습니다 (그 동기 대응 performBlockAndWait 반대)

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObjectContext *context = [self managedObjectContext]; 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     NSManagedObject *m = [self.tests objectAtIndex:indexPath.row]; 
     [context performBlock:^{ 
      [context deleteObject:m]; 

      if (![context save:&error]) { 
       //Note: You should really do something more useful than log this 
       NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]); 
      } 
     }]; 
     [self.tests removeObjectAtIndex:indexPath.row]; 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

performBlock 호출이 비동기입니다.

관리 객체 컨텍스트 인스턴스가 자주 변경되지 않아야합니다. 소규모 응용 프로그램에서는 수명주기 동안 NSManagedObjectContxt의 단일 인스턴스 만 할당하는 것이 일반적입니다.

+0

감사! 이것은 작동하는 것 같습니다. 그냥 궁금 해서요 : NSPrivateQueueConcurrencyType 만 사용하면 괜찮습니까? – jcr

+0

performBlock/perfomBlockAndWait을 사용하여 관리 대상 객체에서 읽을 수 있으면 좋습니다. 특히 Tableview 코드는 performBlockAndWait 호출에서 값을 복사하여 셀에 설정해야하기 때문에 약간 어색합니다. NSMainQueueConcurrencyType으로 시작 (블록에서 셀 속성을 설정할 수 있도록) 한 다음 의미가있는 경우 개인 대기열로 전환하십시오. – ImHuntingWabbits

1

context에서 object 만 삭제할 수 있습니다. 해당 관리 객체를 가져온 위치입니다. 새로운 컨텍스트와 seprate thread를 사용하는 경우, 그 경우에 당신은 당신이 NSManagedObjectID이 컨텍스트 사이의 동일 객체

[context objectWithID:objectId]]; 

를 삭제할 수 있도록 managedObject에서 objectId가 첫 번째 상황에서 가져온 얻을 수 있지만, NSManagedObject 자체합니다 아니다.

+1

(1) 관리 대상 객체가 영구 저장소에 있다고 가정합니다. –

+0

모든 정상적인 작업이 컨텍스트에서 수행됩니다 ... –

1

다른 대답은 언급 한대로 컨텍스트에서 개체를 삭제할 수 있으며 컨텍스트는 스레드에 바인딩되어 있습니다. 여기서 문제는 저장하는 데 걸리는 시간이 아니라 저장할 위치입니다.

이와 같은 메서드 호출에 직면 한 모든 UI에서 값 비싼 작업을하지 않아야합니다. 삭제 직후에 저장할 이유가 없습니다. 나중에 저장하십시오. 사용자가 UI에서 지연이 예상되는 경우 저장하십시오. 핵심 데이터는 저장하지 않고도 정상적으로 작동합니다.

관련 문제