Оптимизация основных данных - PullRequest
1 голос
/ 23 января 2012

У меня есть большой список пользователей в NSDictionary, который имеет такую ​​структуру:

        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
         }

Я хочу ввести эти данные в базовые данные. Сначала я должен проверить, существует ли пользователь в основных данных. Если это так, обновите этого пользователя. В противном случае создайте нового пользователя. То, как я это делаю, работает, но очень медленно. Вот мой код:

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.");
    }
}

А вот и мой способ обновить контакт

+(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;
}

Может ли кто-нибудь дать мне пример того, как я мог бы сделать это намного быстрее? Некоторые люди упомянули некоторые идеи, но мне нужно увидеть это, чтобы понять. Спасибо!

Ответы [ 2 ]

2 голосов
/ 23 января 2012

Прежде всего, я бы перешел сохранить: вне цикла.Замените:

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

на

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

Кроме того, есть ли у вас значения по умолчанию для imageURL, imageThumb и locationName, определенные в модели Core Data?Если нет, почему вы проверяете наличие нулей (дважды)?

Бонус:

Это может быть хорошей идеей для исключения countForEntity: withPredicate: andContext: call, напримерэто:

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];
}
1 голос
/ 23 января 2012

Вы должны понимать, что запрос на выборку является дорогостоящим (он должен запускать SQL и выполнять ввод / вывод). Я не уверен, откуда взялся ваш CoreDataHelper, но он сделает что-то вроде NSFetchRequest, что дорого. Вы можете создать один NSFetchRequest, который скажет вам, какие объекты уже существуют. Это уменьшит стоимость с O (N) до O (1).

[request setPredicate:[NSPredicate predicateWithFormat:@"userID IN %@", allKeys]];

И, как отмечалось выше, выведите сейвы из цикла. Но если вы обновляете, добавляя много объектов, вы можете время от времени сохранять.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...