Базовые данные не сохраняют объекты и работают медленно - PullRequest
0 голосов
/ 24 декабря 2011

Я впервые работаю с Core Data, в качестве руководства я использую курс по разработке приложений для Stanford для iOS.Я в значительной степени скопировал код из демонстрационного приложения (конечно, я настроил его под свои нужды), но в настоящее время у меня две проблемы.

Мое приложение представляет собой вид карты, который при нажатии кнопки представляетмодальный контроллер вида.Это модальное представление проверяет, был ли создан UIManagedDocument.Если нет, он создает один и вставляет данные.Эти данные поступают из списка свойств (258 элементов, так что ничего лишнего).Если он уже был создан (путем предварительного отображения этого представления), если моя логика верна, можно с уверенностью предположить, что он также имеет содержимое, поскольку NSManagedObject s создаются одновременно с созданием документа.Первый запуск работает отлично, таблица загружается, и все мои данные отображаются правильно.

Однако, когда я отклоняю, а затем повторно отображаю мое модальное представление, таблица остается пустой.Я проверяю состояние документа, которое равно UIDocumentStateNormal, поэтому запросить его должно быть в порядке.Но это не так: мой fetchedResultsController возвращает 0 строк.Если я правильно понимаю UIManagedContext, то поведение, которое я испытываю, может быть вызвано неверным / другим контекстом, но я уверен, что: 1) Я передаю свой документ (а не только контекст) модальному представлению в prepareForSegue:senderи 2) я передаю свой документ с контекстом обратно представлению представления, когда модальное представление отклоняется.Вот почему я думаю, что это, вероятно, не контекст, а что-то другое.

Еще одна вещь: вставка 258 записей при первом запуске приложения в симуляторе достаточно быстрая.Однако на моем телефоне это может занять целых 13 секунд.Код вставки показан ниже (изменен для удобства чтения):

+ (Department *)departmentName:(NSString *)name
                withAttributes:(NSDictionary *)attributes
                     inContext:(NSManagedObjectContext *)context {

    Department *department = [NSEntityDescription insertNewObjectForEntityForName:@"Department" inManagedObjectContext:context];
        department.name = name;

        NSArray *informationElements = [attributes objectForKey:@"information"];

        for (int i = 0; i < [informationElements count]; i++) {
            NSString *informationValue = [[informationElements objectAtIndex:i] objectForKey:@"value"];

            if ([[[informationElements objectAtIndex:i] objectForKey:@"description"] isEqualToString:@"phone"]) {
                department.phone = informationValue;
            } else if ([[[informationElements objectAtIndex:i] objectForKey:@"description"] isEqualToString:@"email"]) {
                department.email = informationValue;
            } else if ([[[informationElements objectAtIndex:i] objectForKey:@"description"] isEqualToString:@"web"]) {
                department.website = informationValue;
            }
        }   
    return department;
}

Для ясности: этот код работает просто отлично, но он очень медленный.Он заключен в метод, который вызывается ровно 258 раз.informationElements имеет не более трех элементов, что означает, что максимум 258 * 3 = 774 цикла.На самом деле это гораздо меньше, но даже если бы это было 774, это не должно занять 13 секунд, верно?

Фрагмент ниже показывает инициализацию UIManagedDocument:

if (![[NSFileManager defaultManager] fileExistsAtPath:[self.database.fileURL path]]) {
    [self.database saveToURL:self.database.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
        [self setupFetchedResultsController];
        [self fetchDepartmentsIntoDocument:self.database];
    }];
} else if (self.database.documentState == UIDocumentStateClosed) {
    [self.database openWithCompletionHandler:^(BOOL success) {
        [self setupFetchedResultsController];
    }];
} else if (self.database.documentState == UIDocumentStateNormal) {
    [self setupFetchedResultsController];
}

fetchDepartmentsIntoDocument читает список свойств и затем запускает цикл, который вызывает departmentName:withAttributes:inContext для каждого элемента списка свойств.

Если кто-нибудь может оказать мне некоторую помощь, это будет высоко ценится!

Ответы [ 2 ]

1 голос
/ 24 декабря 2011

Что касается скорости, я бы хотел использовать предикаты;это должно ускорить процесс!

Предикаты позволяют сделать так, чтобы контекст возвращал только те значения, которые необходимы на основе выбранных вами критериев.Причина, по которой они работают быстрее, заключается в том, что ему не нужно преобразовывать каждый сохраненный объект в управляемый объект, скорее он может извлекать данные прямо из свойства, что значительно ускоряет сравнение.

0 голосов
/ 26 декабря 2011

Когда вы вставляете объекты Department в контекст, вы сохраняете данные для каждого объекта? Вставка является относительно дешевой, но сохранение (т.е. -[NSManagedobjectContext save:]) стоит дорого (поскольку база данных должна выполнять блокировку и файловый ввод / вывод).

Кроме того, на более стилистической ноте вы можете сделать

    for (NSDictionary *element in informationElements) {
        NSString *informationValue = [element objectForKey:@"value"];

        if ([[element objectForKey:@"description"] isEqualToString:@"phone"]) {
            department.phone = informationValue;
        } else if ([[element objectForKey:@"description"] isEqualToString:@"email"]) {
            department.email = informationValue;
        } else if ([[element objectForKey:@"description"] isEqualToString:@"web"]) {
            department.website = informationValue;
        }
    }   

для перебора массива словарей.

...