【问题标题】:Magical Record background save seems to be blocking UIMagical Record后台保存似乎阻止了UI
【发布时间】:2013-06-22 16:19:09
【问题描述】:

我有一个 NSOperation 放入队列中。 NSOperation 进行一些长时间运行的照片处理,然后我将信息/元数据保存在该照片的核心数据中。在我的自定义 NSOperation 类的主要方法中,我执行以下代码块

-(void)main
{
    //CODE ABOVE HANDLES PHOTO PROCESSING...
    //........

    //THEN I SAVE ALL DATA BELOW LIKE SO
    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

        Post *post = [Post createInContext:localContext];

        //set about 15 pieces of data, all strings and floats
        post.XXXX = XXXXX;
        post.DDDD = DDDDD;
        etc...
    } completion:^(BOOL success, NSError *error) {
        NSLog(@"Done saving");
    }];
}

我的问题是,即使保存时只有 3 张照片,它也确实冻结了我的 UI。我本来以为在 NSOperation 中执行这个我会没事的。

我应该补充一点,每个 NSOperation 处理一张照片,所以有时队列可能有 5-10 张照片,但我认为这不会有任何区别,即使只有三张就像我说的那样冻结 UI。

感谢您的帮助。

更新:------------*-------------

我切换到了 2.2 版,但这似乎更加阻塞了 UI……我现在也在使用

-(void)main
{
    NSManagedObjectContext *localContext = [NSManagedObjectContext    contextForCurrentThread];
    //CODE BELOW HANDLES PHOTO PROCESSING...
    //........

    //THEN I SAVE ALL DATA BELOW LIKE SO
    Post *post = [Post createInContext:localContext];

    //set about 15 pieces of data, all strings and floats
    post.XXXX = XXXXX;
    post.DDDD = DDDDD;


    [localContext saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {

    }];
}

这都是在我的 NSOperation 类中完成的,我做错了吗?

【问题讨论】:

  • 如何开始操作?
  • 您是否进行了分析以确定延迟的确切位置?
  • 只要处理发生在主线程中,你的用户界面就会冻结。

标签: ios core-data nsoperation magicalrecord


【解决方案1】:

不要将 saveWithBlock 调用放在后台线程中。您正在有效地从后台线程创建后台线程,在这种情况下,这只会减慢您的速度。您应该能够调用 saveWithBlock 并且它应该将所有保存代码放在后台。但是,我还注意到您在代码的主 UI 页面中进行了所有更改,之后才调用 save。这是这种方法的错误用法。你想做更多这样的事情:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    Post *post = [Post createInContext:localContext];

    //photo processing
    //update post from photo processing
} completion:^(BOOL success, NSError *error) {
   //This is called when data is in the store, and is called on the main thread
}];

如果您确实需要 NSOperation,我建议使用不同的模式:

- (void) main {
   NSManagedObjectContext *localContext = [NSManagedObjectContext confinementContext];
  // Do your photo stuff here

  Post *post = [Post createInContext:localContext];
  //more stuff to update post object

  [localContext saveToPersistentStoreAndWait];

}

【讨论】:

  • 感谢您的帮助,我在线程中古怪的代码和线程放置似乎是问题所在。我还更新到了 2.2 版,这似乎也有所帮助。我最终使用了您建议的 saveWithBlock,确实不需要 NSOperation。
【解决方案2】:

在开始操作时要小心。

[operation start]

将在当前线程上启动操作,因此如果您从主线程(即 UI 线程)调用它,它将阻塞界面。

您应该将操作添加到队列中,以便它在后台运行而不会占用主线程

[[NSOperationQueue new] addOperation:operation];

【讨论】:

  • 我按照你上面所说的开始。
  • 对不起,我应该更清楚 [[NSOperationQueue new] addOperation:operation];
  • 我切换到标签 2.2,这似乎甚至更糟地阻塞了 UI。我会尝试做一些分析,但任何建议都将不胜感激。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多