在后台线程上执行Core Data保存?

Luk*_*uke 1 structure core-data objective-c nsmanagedobjectcontext ios

我有一个按钮,它将Core Data SQLite中的一个选定条目标记为"收藏夹",这意味着我只是BOOL将该索引从off更改为on.

目前,当我这样做,我叫save上了managedObjectContext,这也许需要500毫秒,更也许有点,根据仪器.

我有一些代码同时执行,触发了一个漂亮的小粒子爆炸("万岁,最喜欢的!"),但我遇到的问题是爆炸延迟到save完成之后.

我不知道为什么,因为触发爆炸的代码是在save调用之前.我是一个相对较新的程序员,所以也许我错过了一些东西,但是在这样的情况下不会逐行执行代码执行,因为爆炸会触发,然后保存将在它发生时发生?这里的委托调用也可能需要一些时间,但同样的问题适用,为什么它会在这些代码行之后重要?

编辑:我是否正确地说,在下一行代码出现粒子之前,主线程被阻塞,这意味着UI无法自行更新?

这是我的代码:

// Particle animation
LikeExplosion *likeExplosionView = [[LikeExplosion alloc] initWithFrame: CGRectMake(0, 0, 320, 400)];
[likeExplosionView setUserInteractionEnabled: NO];
[self.view addSubview: likeExplosionView];
[self.view bringSubviewToFront: likeExplosionView];
[likeExplosionView decayOverTime: 1.1];

// Delegate call to reload tableview elsewhere
[self.delegate detailViewControllerDidLikeLine];

// Update current object
[_selectedLine setIsLiked: [NSNumber numberWithBool: YES]];
[_selectedLine setIsDisliked: [NSNumber numberWithBool: NO]];

// Update context
NSError *error;
if (![[[CDManager sharedManager] managedObjectContext] save:&error]) NSLog(@"Saving changes failed: %@, %@", error, [error userInfo]);
Run Code Online (Sandbox Code Playgroud)

第一个问题:当我在方法中首先调用动画代码时,为什么会出现延迟?

第二个问题:调用问题放在save后台线程上解决问题,这样做是否安全/好主意?

Gob*_*bot 11

动画,通常与UI有关的任何事情都在主线程上执行.如果你不希望持久化到磁盘(保存处理)托起你的UI(主线程),你需要通过把上下文它自己的私人队列NSManagedObjectContextinitWithConcurrencyType:方法.专用队列将处理与您的上下文有关的任何后台线程.这三种类型是:

NSConfinementConcurrencyType
NSPrivateQueueConcurrencyType
NSMainQueueConcurrencyType      
Run Code Online (Sandbox Code Playgroud)

你想要的NSPrivateQueueConcurrencyType.

您可以通过使用具有不同并发类型的子/嵌套托管对象上下文来采用更复杂的体系结构路由,但如果您是Core Data的新手,请坚持使用单个上下文,直到您牢牢掌握上下文和队列.


Dan*_*lly 7

1)在主runloop完成其循环之前,您的动画将不会开始运行.这个循环不会像save:阻塞方法那样完成.

2)将保存移动到后台线程将解决问题,但您必须访问managedObjectContext主线程中的main,因此,您必须使用后台上下文:

NSManagedObjectContext* context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(mergeChanges:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:context];
[context performBlock:^{
    //make changes
    NSError* error = nil;
    [context save:&error];
    //remember to remove observer after the save (in mergeChanges: and dealloc)
}];
Run Code Online (Sandbox Code Playgroud)

您可以通过使用以下方法在下一个runloop中的主线程上安排保存来启动动画而不移动到后台: [self performSelectorOnMainThread:@selector(saveMain) withObject:nil waitUntilDone:NO];