Core data 核心数据在多次保存时冻结应用程序

Core data 核心数据在多次保存时冻结应用程序,core-data,moc,Core Data,Moc,我无法将数据保存在核心数据中。我必须点击按钮在数据库中保存多个图书信息。当我点击按钮时,我调用该方法并将图书信息保存在数据库中。对于前三次点击,它很好地保存了图书信息,用户界面也响应良好。当我第四次单击按钮时,ui在保存结束时冻结 代码如下所示 +(void) storeBookInfo:(NSDictionary *) bookInfo inContext:(NSManagedObjectContext *) ctx { AppDelegate *appDelegate = (App

我无法将数据保存在核心数据中。我必须点击按钮在数据库中保存多个图书信息。当我点击按钮时,我调用该方法并将图书信息保存在数据库中。对于前三次点击,它很好地保存了图书信息,用户界面也响应良好。当我第四次单击按钮时,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,因为代码在后台线程中,每次保存后我都会发送通知

第四次点击按钮“应用程序冻结”。我被困在这一点上。

*假设:

+storeBookInfo:inContext:
始终在BG线程中调用

使用弧

*请注意:

<代码> >代码> > StuteBooKof:InWrime:<代码>是类本身,<代码> ReaveValue:<代码>它将删除所有的观察信息(您可能错过某个时间的合并,考虑使用<代码> ReaveValue:No:对象:< /Cord>,而不是立即取消TEMPPCTX)

您正在使用:
NSPrivateQueueConcurrencyType
但未使用它的
performBlock:
performBlockAndWait:
方法(考虑使用
nsConfiginementConcurrencyType

如果
+mergeChanges:
将在主线程上被调用,则应用程序将被卡住 (考虑加入:

    NSAssert(![NSThread isMainThread],@"The application will get stuck");
以确保或修改合并流 )