2013-03-29 5 views
0

코어 데이터에 데이터를 저장하는 데 문제가 있습니다. 나는 클릭하여 데이터베이스에 여러 책 정보를 저장해야한다. 버튼을 클릭하면 메소드가 호출되고 데이터베이스에 책 정보가 저장됩니다. 처음 세 번 클릭하면 책 정보가 저장되고 ui도 응답합니다. 네 번째 버튼을 클릭하면 ui는 저장이 끝나면 고정됩니다.코어 데이터가 여러 저장시 앱을 고정합니다.

코드는 아래와 같습니다.

+(void) storeBookInfo:(NSDictionary *) bookInfo inContext:(NSManagedObjectContext *) ctx { 

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 

    NSManagedObjectContext *tempCtx = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    [tempCtx setPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator]; 
    [tempCtx setUndoManager:nil]; 

    NSNotificationCenter *notify = [NSNotificationCenter defaultCenter]; 
    [notify addObserver:self 
       selector:@selector(mergeChanges:) 
        name:NSManagedObjectContextDidSaveNotification 
       object:tempCtx]; 

    NSFetchRequest *req = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:tempCtx]; 
    [req setEntity:entity]; 

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bid==%@", [bookInfo objectForKey:@"bid"]]; 
    [req setPredicate:predicate]; 

    [req setFetchLimit:1]; 
    [req setReturnsObjectsAsFaults:NO]; 
    NSArray *bookObjects = [tempCtx executeFetchRequest:req error:nil]; 
    if([bookObjects count] > 0){ 
     NSError *err; 
     Book *wi = [bookObjects objectAtIndex:0]; 
     wi.purchaseInfo = [NSNumber numberWithInt:[[bookInfo objectForKey:@"purchaseInfo"] intValue]]; 
     if (![tempCtx save:&err]) { 
      NSLog(@"Problem saving book info.."); 
      NSLog(@"err: %@", [err userInfo]); 
      [[NSNotificationCenter defaultCenter] removeObserver:self]; 
      [tempCtx undo]; 
      tempCtx = nil; 

     } else { 
      NSLog(@"Book saved. in if part"); 
      tempCtx = nil; 
      [[NSNotificationCenter defaultCenter] removeObserver:self]; 
     } 
    } 
    else { 

     Book *book = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:tempCtx]; 
     book.bid  = [bookInfo objectForKey:@"bid"]; 
     book.title = [bookInfo objectForKey:@"title"]; 
     book.thumbnailImgId = [bookInfo objectForKey:@"imageUrl"]; 
     book.downloadState = [NSNumber numberWithInt:0]; 
     book.pid = [bookInfo objectForKey:@"pid"]; 
     book.purchaseInfo = [NSNumber numberWithInt:[[bookInfo objectForKey:@"purchaseInfo"] intValue]]; 
     book.discription = [bookInfo objectForKey:@"desc"]; 
     NSError *err; 
     if (![tempCtx save:&err]) { 
      NSLog(@"Problem saving book ifo.."); 
      NSLog(@"err: %@", [err userInfo]); 
      [[NSNotificationCenter defaultCenter] removeObserver:self]; 
      [tempCtx undo]; 
      tempCtx = nil; 

     } else { 

      NSLog(@"Book saved."); 
      tempCtx = nil; 
      [[NSNotificationCenter defaultCenter] removeObserver:self]; 
     } 
    } 

} 

+ (void)mergeChanges:(NSNotification*)notification 
{ 
    AppDelegate *theDelegate = [[UIApplication sharedApplication] delegate]; 
    [[theDelegate managedObjectContext]   performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES]; 

} 

코드가 백그라운드 스레드에 있고 각 저장 후에 알림을 보내면 임시 MOC를 만들었습니다.

버튼을 네 번 클릭하면 앱이 정지됩니다. 나는이 시점에서 붙어있다.

답변

0

* 가정 :

이 에게 +storeBookInfo:inContext: 항상 * 참고 ARC

사용 BG 스레드

에라고

: +storeBookInfo:inContext:에서

self 클래스 자체가, 그 위에 removeObserver: 모두 제거합니다 관측 정보 (특정 타이밍에 병합이 누락 될 수 있으므로 대신 removeObserver:name:object:을 사용하고 tempCtx 권한을 무효로하지 않는 것이 좋습니다.) 멀리)

사용중인 : NSPrivateQueueConcurrencyType를하지만 performBlock: 또는 performBlockAndWait: 방법의 사용하지 않는 +mergeChanges: 이제까지 주 스레드에서 호출되는 경우 (추가하는 것을 고려 (응용 프로그램이 붙어 을 얻을 것이다 NSConfinementConcurrencyType)

을 사용하는 것이 좋습니다 :

NSAssert(![NSThread isMainThread],@"The application will get stuck"); 

것은 확인하거나 병합 )

흐름 개정
관련 문제