Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 核心数据存储和UI性能_Iphone_Objective C_Cocoa Touch_Core Data - Fatal编程技术网

Iphone 核心数据存储和UI性能

Iphone 核心数据存储和UI性能,iphone,objective-c,cocoa-touch,core-data,Iphone,Objective C,Cocoa Touch,Core Data,我想知道,在使用大量托管对象集合进行核心数据保存(而不是获取)时,是否有任何最佳做法可以提高UI响应能力 我正在开发的应用程序需要每隔一段时间从web服务下载大量数据,直到完成。在每个时间间隔,将下载一批数据,将其格式化为托管对象,并将其保存到核心数据中。因为这个过程有时可能需要5分钟才能完全完成,所以简单地添加一个加载屏幕直到所有事情完成并不是一个真正的选项,它需要太长的时间。我还对频繁写入核心数据感兴趣,而不是在最后进行一次大的写入,以保持较低的内存占用。理想情况下,我希望用户能够继续正常使

我想知道,在使用大量托管对象集合进行核心数据保存(而不是获取)时,是否有任何最佳做法可以提高UI响应能力

我正在开发的应用程序需要每隔一段时间从web服务下载大量数据,直到完成。在每个时间间隔,将下载一批数据,将其格式化为托管对象,并将其保存到核心数据中。因为这个过程有时可能需要5分钟才能完全完成,所以简单地添加一个加载屏幕直到所有事情完成并不是一个真正的选项,它需要太长的时间。我还对频繁写入核心数据感兴趣,而不是在最后进行一次大的写入,以保持较低的内存占用。理想情况下,我希望用户能够继续正常使用应用程序的其余部分,同时下载这些大型数据集并将其写入核心数据

不幸的是,当我试图保存插入到每个批的托管对象上下文中的插入内容时,保存操作会阻止用户在完成之前与应用程序的其余部分交互(刷表、触摸按钮等)。在核心数据保存的短时间内,应用程序的响应非常迟钝

当然,我已经尝试通过减少每间隔下载的单个批的大小来减小这些保存,但是除了使整个过程花费更长时间带来的不便之外,仍然会有用户的刷卡未被捕获的情况,因为在特定的时间发生了核心数据保存。缩小尺寸只会降低漏刷或漏碰的可能性,但这种情况似乎仍然经常发生,给您带来不便

对于插入本身,我尝试使用两种不同的实现:insertNewObjectForEntityForName:inManagedObjectContext和setValuesForKeysWithDictionary。两者都表现出我上面描述的问题

我尝试了一个简单得多的测试原型,以查看模拟器和设备的性能,我在这里提供了重要的元素。这个示例实际上并没有从web下载任何内容,只是在TableViewController中按设定的时间间隔将一大堆内容写入核心数据。我很想知道是否有人对提高响应能力有任何建议

- (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");
    }
}
-(void)视图显示:(BOOL)动画
{
[超级视图显示:动画];
计时器=[NSTimer scheduledTimerWithTimeInterval:1目标:自选择器:@selector(doTimerWork:)用户信息:无重复:是];
}
-(无效)doTimerWork:(id)发件人
{
对于(int i=0;i<1000;i++)
{
Misc*m=(Misc*)[NSEntityDescription insertNewObjectForEntityForName:@“Misc”在managedObjectContext:managedObjectContext中];
m、 someDate=[NSDate-date];
m、 someString=@“ASDASDASD”;
m、 someOtherString=@“诸如此类”;
m、 someNumber=[NSNumber numberwhithint:5];
m、 someOtherNumber=[NSNumber numberWithInt:99];
m、 someOtherDate=[NSDate-date];
}
n错误*错误;
如果(![managedObjectContext保存:&错误]){
NSLog(@“保存到CoreData时遇到错误”);
}
}

听起来您需要将包含核心数据的数据密集型内容放到一个单独的线程中,幸运的是,这在Cocoa中非常容易。您只需执行以下操作:

[obj performSelectorInBackground: @selector(method:) withObject: arg];
然后进行设计,一旦数据密集型操作完成,调用:

[otherObject performSelectorOnMainThread: @selector(dataStuffIsDone:) withObject: arg waitUntilDone: NO];
此时您可以更新UI


要记住的主要一点是始终将UI逻辑保留在主线程上,这既有利于正确的设计,也有利于从不同的线程使用
UIKit
执行任何操作,因为它不是线程安全的

通常,您会在后台线程上下载数据,并将托管对象插入/更新到其托管对象上下文中。
在主线程上,您将注册并接收
NSManagedObjectContextWillSaveNotification
,并使用
mergeChangesFromContextDidSaveNotification:
更新主托管对象上下文

这就是你在做的吗


另外,请阅读。

感谢您的提示,我在研究多线程解决方案时有点犹豫,但是,通过将托管对象创建和保存移动到后台线程,我能够极大地提高性能,如下所述。
NSManagedObjectContext
不是线程安全的,您在其上创建的任何对象都不是线程安全的。在谈论核心数据时,将您正在做的事情从前台线程转移到后台线程显然是不安全的。有关适当解决方案的信息,请参阅gerry3帖子中的链接。