批量更新&偶尔插入(coredata)-太慢
更新:目前正在研究 NSSET 的 minusSet 链接: 比较两个数组
大家好,
可以从你们的智慧中受益。
我正在使用 Coredata我的应用程序,第一次启动时,我下载一个数据文件并插入 500 多个对象(每个对象有 60 个属性)——速度很快,没问题。
每次后续启动时,我都会下载该文件的更新版本,从中我需要更新所有现有对象的属性(可能除了 5 个属性),并为已添加到下载文件中的项目创建新属性。
因此,第一次启动我得到 500 个对象。假设一周后,我的文件现在包含 507 个项目。
我创建两个数组,一个用于现有数组,一个用于下载。
NSArray *peopleArrayDownloaded = [CoreDataHelper getObjectsFromContext:@"person" :@"person_id" :YES :managedObjectContextPeopleTemp];
NSArray *peopleArrayExisting = [CoreDataHelper getObjectsFromContext:@"person" :@"person_id" :YES :managedObjectContextPeople];
如果每个数组的计数相等,那么我就这样做:
NSUInteger index = 0;
if ([peopleArrayExisting count] == [peopleArrayDownloaded count]) {
NSLog(@"Number of people downloaded is same as the number of people existing");
for (person *existingPerson in peopleArrayExisting) {
person *tempPerson = [peopleArrayDownloaded objectAtIndex:index];
// NSLog(@"Updating id: %@ with id: %@",existingPerson.person_id,tempPerson.person_id);
// I have 60 attributes which I to update on each object, is there a quicker way other than overwriting existing?
index++;
}
} else {
NSLog(@"Number of people downloaded is different to number of players existing");
现在是缓慢的部分。
我最终使用了这个(太慢了):
NSLog(@"Need people added to the league");
for (person *tempPerson in peopeArrayDownloaded) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"person_id = %@",tempPerson.person_id];
// NSLog(@"Searching for existing person, person_id: %@",existingPerson.person_id);
NSArray *filteredArray = [peopleArrayExisting filteredArrayUsingPredicate:predicate];
if ([filteredArray count] == 0) {
NSLog(@"Couldn't find an existing person in the downloaded file. Adding..");
person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"person" inManagedObjectContext:managedObjectContextPeople];
有没有办法生成一个新的索引项数组,引用我下载的文件中的附加项目?
顺便说一句,在我的 tableViews 上,我使用 NSFetchedResultsController 因此更新属性将调用 [cell setNeedsDisplay]; .. 每个单元大约 60 次,这不是一件好事,它可能会使应用程序崩溃。
感谢您的阅读:)
Update: Currently looking into NSSET's minusSet
links: Comparing Two Arrays
Hi guys,
Could benefit from your wisdom here..
I'm using Coredata in my app, on first launch I download a data file and insert over 500 objects (each with 60 attributes) - fast, no problem.
Each subsequent launch I download an updated version of the file, from which I need to update all existing objects' attributes (except maybe 5 attributes) and create new ones for items which have been added to the downloaded file.
So, first launch I get 500 objects.. say a week later my file now contains 507 items..
I create two arrays, one for existing and one for downloaded.
NSArray *peopleArrayDownloaded = [CoreDataHelper getObjectsFromContext:@"person" :@"person_id" :YES :managedObjectContextPeopleTemp];
NSArray *peopleArrayExisting = [CoreDataHelper getObjectsFromContext:@"person" :@"person_id" :YES :managedObjectContextPeople];
If the count of each array is equal then I just do this:
NSUInteger index = 0;
if ([peopleArrayExisting count] == [peopleArrayDownloaded count]) {
NSLog(@"Number of people downloaded is same as the number of people existing");
for (person *existingPerson in peopleArrayExisting) {
person *tempPerson = [peopleArrayDownloaded objectAtIndex:index];
// NSLog(@"Updating id: %@ with id: %@",existingPerson.person_id,tempPerson.person_id);
// I have 60 attributes which I to update on each object, is there a quicker way other than overwriting existing?
index++;
}
} else {
NSLog(@"Number of people downloaded is different to number of players existing");
So now comes the slow part.
I end up using this (which is tooooo slow):
NSLog(@"Need people added to the league");
for (person *tempPerson in peopeArrayDownloaded) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"person_id = %@",tempPerson.person_id];
// NSLog(@"Searching for existing person, person_id: %@",existingPerson.person_id);
NSArray *filteredArray = [peopleArrayExisting filteredArrayUsingPredicate:predicate];
if ([filteredArray count] == 0) {
NSLog(@"Couldn't find an existing person in the downloaded file. Adding..");
person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"person" inManagedObjectContext:managedObjectContextPeople];
Is there a way to generate a new array of index items referring to the additional items in my downloaded file?
Incidentally, on my tableViews I'm using NSFetchedResultsController so updating attributes will call [cell setNeedsDisplay];
.. about 60 times per cell, not a good thing and it can crash the app.
Thanks for reading :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先我要说的是,我对使用核心数据框架仍然很陌生,但我的猜测是您的问题在于您发布的 for 循环。
如果您查看循环,每次执行时都会创建一个新的 NSPredicate 对象,然后过滤现有数组以查找匹配项。在小数据集上,这种技术的性能损失看似很小。然而,对于大型数据集,您最终将花费大量时间创建仅在您提供的名称上有所不同的 NSPredicate 对象。我建议您了解如何创建单个谓词,然后使用变量替换来执行搜索。有关谓词中变量使用的信息,请查看:http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174
作为旁注,您还可以考虑如何对数据进行排序以及如何执行搜索操作。我注意到的另一件事是,您没有释放 NSPredicate 对象,因此您也只是在扔掉内存。
I'll begin by saying that I'm still new to using the Core Data framework, but my guess is that your problem lies in the for loop you've posted.
If you look at your loop, each time it executes it creates a new NSPredicate object and then filters your existing array looking for matches. On a small data set this technique would work with seemingly small performance losses; however, with your large data set you will end up spending a lot of time creating NSPredicate objects that only differ in the name you've provided. I would suggest that you look at how to create a single predicate and then use variable substitution to perform the search. For information about variable use in predicates check out: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174
As a side note, you may also consider how you've sorted your data and how you are performing the search operation. And another thing I noticed is that you don't release your NSPredicate object, so you're just tossing memory away too.