首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >核心数据优化

核心数据优化
EN

Stack Overflow用户
提问于 2012-01-24 00:10:30
回答 2查看 960关注 0票数 1

我在NSDictionary中有一个很大的用户列表,它的结构如下:

代码语言:javascript
复制
        97 =             {
            birthday = "";
            gender = Unspecified;
            image =                 {
                status = Prepared;
                type = Image;
            };
            "name_display" = "Facebook User";
            "name_first" = Facebook;
            "name_last" = User;
            type = Contact;
            "user_id" = 97;
        };
        98 =             {
            birthday = "";
            gender = Unspecified;
            image =                 {
                status = Prepared;
                type = Image;
            };
            "name_display" = "Facebook User";
            "name_first" = Facebook;
            "name_last" = User;
            type = Contact;
            "user_id" = 98
         }

我想将此数据输入到Core Data中。首先,我必须检查用户是否已经存在于核心数据中。如果是,则更新该用户。否则,创建一个新用户。我做这件事的方式是有效的,但它非常慢。下面是我的代码:

代码语言:javascript
复制
NSDictionary *users = [responseData objectForKey:@"users"];
if (users) {
    for (id userKey in [users allKeys]) {
        NSDictionary *contactDictionary = [users objectForKey:userKey];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"userID == %@", userKey];
        NSUInteger count = [CoreDataHelper countForEntity:@"Contact" withPredicate:predicate andContext:[FSAppDelegate managedObjectContext]];
        if (count > 0) {
            NSMutableArray *existingContactArray = [CoreDataHelper searchObjectsForEntity:@"Contact" withPredicate:predicate andSortKey:nil andSortAscending:NO andContext:[FSAppDelegate managedObjectContext]];
            Contact *existingContact = [existingContactArray objectAtIndex:0];
            [CoreDataHelper updateContactWithDictionary:contactDictionary forContactObject:existingContact];
        }
        else {
            Contact *newContact = (Contact*)[NSEntityDescription insertNewObjectForEntityForName:@"Contact" inManagedObjectContext:[FSAppDelegate managedObjectContext]];
            [CoreDataHelper updateContactWithDictionary:contactDictionary forContactObject:newContact];
        }
    }

    NSError *error;
    if (![[FSAppDelegate managedObjectContext] save:&error]) {
        // Handle the error.
        NSLog(@"error saving to db - fsrequest class.");
    }
}

下面是我更新联系人的方法

代码语言:javascript
复制
+(BOOL)updateContactWithDictionary:(NSDictionary*)changedContact forContactObject:(Contact*)contact {
NSString *bday = [changedContact valueForKey:@"birthday"];
NSString *gender = [changedContact valueForKey:@"gender"];
NSString *nameDisplay = [changedContact valueForKey:@"name_display"];
NSString *nameFirst = [changedContact valueForKey:@"name_first"];
NSString *nameLast = [changedContact valueForKey:@"name_last"];
NSString *type = [changedContact valueForKey:@"type"];
NSString *userID = [NSString stringWithFormat:@"%@",[changedContact valueForKey:@"user_id"]];
NSString *imageStatus = [[changedContact objectForKey:@"image"]objectForKey:@"status"];
NSString *imageType = [[changedContact objectForKey:@"image"]objectForKey:@"type"];
NSString *imageURL = [[changedContact objectForKey:@"image"]objectForKey:@"url"];
NSString *imageThumb = [[changedContact objectForKey:@"image"]objectForKey:@"url_thumb"];
NSString *locationName = [[changedContact objectForKey:@"location"]objectForKey:@"name"];

[contact setBirthday:bday];
[contact setGender:gender];
[contact setNameDisplay:nameDisplay];
[contact setNameFirst:nameFirst];
[contact setNameLast:nameLast];
[contact setType:type];
[contact setUserID:userID];
[contact setImageStatus:imageStatus];
[contact setImageType:imageType];
if (imageURL && !((NSNull *)imageURL == [NSNull null])) {
    [contact setImageURL:imageURL];
}
if (imageThumb && !((NSNull *)imageThumb == [NSNull null])) {
    [contact setImageThumbURL:imageThumb];
}
if (locationName && !((NSNull *)locationName == [NSNull null])) {
    [contact setLocationName:locationName];
}
return YES;
}

有没有人能给我举个例子,告诉我如何以一种更快的方式做到这一点?有些人提到了一些想法,但我需要看到它才能理解。谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-24 00:18:07

首先,我将save:移到循环之外。替换:

代码语言:javascript
复制
 // save core data
        NSError *error;
        if (![[FSAppDelegate managedObjectContext] save:&error]) {
            // Handle the error.
            NSLog(@"error saving to db - fsrequest class.");
        }
    }
}

使用

代码语言:javascript
复制
    }
    // save core data
    NSError *error;
    if (![[FSAppDelegate managedObjectContext] save:&error]) {
    // Handle the error.
    NSLog(@"error saving to db - fsrequest class.");
  }
}

另外,您是否在核心数据模型中定义了一些imageURL、imageThumb和locationName的默认值?如果不是,为什么要检查空值(两次)?

奖励:

消除countForEntity:withPredicate:andContext: call可能是个好主意,如下所示:

代码语言:javascript
复制
NSMutableArray *existingContactArray = [CoreDataHelper searchObjectsForEntity:@"Contact" withPredicate:predicate andSortKey:nil andSortAscending:NO andContext:[FSAppDelegate managedObjectContext]];

if ([existingContactArray count] > 0)
{
    Contact *existingContact = [existingContactArray objectAtIndex:0];

    [CoreDataHelper updateContactWithDictionary:contactDictionary forContactObject:existingContact];
}
票数 2
EN

Stack Overflow用户

发布于 2012-01-24 02:21:22

您需要了解fetch请求是昂贵的(它需要运行SQL和执行I/O)。我不知道你的CoreDataHelper是从哪里来的,但它会做一些昂贵的NSFetchRequest。您可以构造一个NSFetchRequest,它将告诉您哪些对象已经存在。这将把成本从O(N)降低到O(1)。

代码语言:javascript
复制
[request setPredicate:[NSPredicate predicateWithFormat:@"userID IN %@", allKeys]];

如上所述,将保存移出循环。如果你正在更新添加一个多个对象,你可能需要时不时地保存。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8974717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档