核心数据保存和UI性能 [英] Core Data Saves and UI Performance

查看:136
本文介绍了核心数据保存和UI性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有任何最佳做法来改善UI响应性,同时使用大量的托管对象进行Core Data保存(而不是提取)。

I'm wondering if there are any best practices for improving UI responsiveness while doing Core Data saves (not fetches) with large collections of managed objects.

我正在开发的应用程序需要从设置的时间间隔从Web服务下载大量数据,直到完成。在每个时间间隔,一批数据被下载,格式化为托管对象,并保存到Core Data。因为这个过程有时可能需要长达5分钟直到完全完成,只需添加一个加载屏幕,直到一切都完成不是一个选项,它需要太长时间。我也有兴趣频繁写入Core Data,而不是最后一个大写,以保持我的内存占用低。理想情况下,我希望用户能够正常使用其余的应用程序,同时下载并将这些大数据集写入Core Data。

The app I'm working on needs to download fairly large amounts of data on set intervals from a web service until complete. On each interval, a batch of data is downloaded, formatted into managed objects, and saved to Core Data. Because this process can sometimes take as long as 5 minutes until fully complete, simply adding a loading screen until everything finishes is not really an option, it takes too long. I'm also interested in doing frequent writes to Core Data, rather than one big write at the end, to keep my memory footprint low. Ideally, I'd like the user to be able to keep using the rest of the application normally, while simultaneously downloading and writing these large data sets to Core Data.

不幸的是,似乎发生的是,当我尝试保存我插入的托管对象上下文为每个批处理,该保存操作阻止用户与其余应用程序交互(滑动表,触摸按钮等)直到完成。对于正在进行核心数据保存的那些短时间段,应用程序是非常无响应的。

Unfortunately, what seems to be happening is that when I try to save my inserts that I put into the managed object context for each batch, that save operation blocks the user from interacting with the rest of the app (swiping tables, touching buttons, etc) until complete. For those short periods of time where a Core Data save is taking place, the app is very unresponsive.

当然,我已经尝试通过减小尺寸的每个间隔下载的每个批次,但是除了使整个过程花费更长时间的不便之外,仍然存在当用户的刷卡未被捕获时的实例,因为在该特定时间正在发生核心数据保存。减小尺寸只会使得错过的滑动或错过的触摸发生的可能性较小,但它们似乎经常发生不足以造成不便。

Naturally, I've tried making those saves smaller by reducing the size of the individual batches that get downloaded per interval, but besides the inconvenience of making the whole process take longer, there will still be instances when a user's swipe is not captured, because at that particular time a core data save was happening. Reducing the size simply makes it less likely that a missed swipe or a missed touch will happen, but they still seem to happen often enough to be inconvenient.

,我试过使用两种不同的实现:insertNewObjectForEntityForName:inManagedObjectContext以及setValuesForKeysWithDictionary。两者都表现出我上面描述的问题。

For the inserts themselves, I've tried using two different implementations: insertNewObjectForEntityForName:inManagedObjectContext as well as setValuesForKeysWithDictionary. Both exhibit the problem I described above.

我尝试了一个更简单的测试,在模拟器和设备上看到性能,我在这里提供了重要的元素。这个例子实际上不从网上下载任何东西,但只是从TableViewController中写入一大堆东西到核心数据在设置的间隔。

I tried prototyping a much simpler test to see performance in both the simulator and on the device, I've provided the important elements here. This example doesn't actually download anything from the web, but just writes a whole bunch of stuff to core data on set intervals from within a TableViewController. I'd love to know if anyone has any suggestions to improve responsiveness.

- (void)viewDidAppear:(BOOL)animated 
{
    [super viewDidAppear:animated];
    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(doTimerWork:) userInfo:nil repeats:YES];
}

-(void) doTimerWork:(id)sender
{
    for (int i = 0; i < 1000; i++)
    {
        Misc * m = (Misc*)[NSEntityDescription insertNewObjectForEntityForName:@"Misc" inManagedObjectContext:managedObjectContext];        
        m.someDate = [NSDate date];
        m.someString = @"ASDASDASD";
        m.someOtherString = @"BLAH BLAH BLAH";
        m.someNumber = [NSNumber numberWithInt:5];
        m.someOtherNumber = [NSNumber numberWithInt:99];
        m.someOtherDate = [NSDate date];    
    }

    NSError *error;
    if (![managedObjectContext save:&error]) {
        NSLog(@"Experienced an error while saving to CoreData");
    }
}


推荐答案

听起来像你需要把你的数据密集的东西用核心数据到一个单独的线程,幸运的是在Cocoa很容易。你可以做:

It sounds like you need to throw your data intensive stuff with Core Data onto a separate thread, which is fortunately pretty easy in Cocoa. You can just do:

[obj performSelectorInBackground: @selector(method:) withObject: arg];

然后设计一些数据密集型操作完成后,调用:

And then design things so that once that data intensive operation is finished, call:

[otherObject performSelectorOnMainThread: @selector(dataStuffIsDone:) withObject: arg waitUntilDone: NO];

此时您可以更新 UI

要记住的主要事情是始终将您的UI逻辑保存在主线程,以便正确设计,如果你使用 UIKit 从不同的线程做任何事情,发生,因为它不是线程安全的。

The main thing to remember is to always keep your UI logic on the main thread, for both proper design, and because very odd things can happen if you do anything with UIKit from a different thread, since it isn't designed to be thread safe.

这篇关于核心数据保存和UI性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆