2011-12-23 3 views
0

Я работаю с Core Data в первый раз, при этом в качестве руководства вы найдете курс разработки приложений для 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 для каждого элемента списка свойств.

Если бы кто-нибудь мог мне помочь, он будет очень признателен!

+0

Вы пробовали его на другую тему? –

+0

У меня нет. Есть ли вероятность, что есть слишком много данных, чтобы справиться с этим достаточно быстро? –

+0

может быть, я использую данные ядра для сохранения моего объекта singleton, и он отлично работает, но ваш выглядит намного сложнее. я говорю это как своего рода заявление на одежде для чего-то, что работает, но медленное. если не было причин подозревать иначе. –

ответ

1

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

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

+0

Да, это был бы вариант, за исключением того, что мне действительно нужны все эти объекты. Это таблица, в которой отображаются все отделы, из которых пользователь может выбрать ее. Если на скорости все не так, мне придется это изменить, но сейчас я хочу посмотреть, есть ли что-то еще, что я мог бы сделать, чтобы поддерживать текущий пользовательский интерфейс со скоростью менее секунды. –

0

Когда вы вставляете объекты объекта в контекст, вы сохраняете для каждого объекта? Вставка относительно дешевая, но экономия (то есть -[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; 
     } 
    } 

итерировать через массив словарей.

+1

Я действительно полагался на механизм автоматического сохранения UIDocument, поэтому я не спасал вообще. Даже при ручном сохранении мои данные не сохраняются между переключателями просмотра. Я также знал о быстром перечислении, но так как мой текущий метод был использован и в лекции, я подумал, что я просто использую это. –

Смежные вопросы