У меня есть модель Core Data, представляющая телегид на iOS 4+, с 3 классами:
Канал
(BBC 1) Программа
(Top Gear) Трансляция
(Top Gear на BBC 1 в понедельник в 20:00) У меня около 40 каналов, 8000 программ и 6000 трансляций, и я хотел бы точно настроить процесс импорта, чтобы он не занимал до минуты.
Импорт каналов и программ прост, потому что это независимые объекты. Однако широковещательная передача имеет отношение к каналу и программе (1-ко-многим), а каналы и программы имеют обратную связь с широковещательными передачами (многие-к-1). Чтобы ускорить процесс, у меня есть словарь в памяти каналов ошибок и программ, для которых предварительно загружен только их идентификатор веб-службы: я создаю широковещательную рассылку и просматриваю оба словаря, чтобы получить соответствующий канал и программу без обращения к базе данных.
Но когда я назначаю программу или канал для трансляции, доступ к каналу и программе с обратной связью сразу вызывает сбой обоих объектов, вызывая значительное замедление (6000 * 2 запросов) и, как следствие, нехватку памяти, как показано в Отчет Core Data Faults Instruments. Я пробовал предварительно загрузить отношения трансляции
на обоих каналах и программах, но отношения все равно нарушаются.
Вы хоть представляете, почему обращаются к обратным отношениям и винят их родителей?Как мне избежать чтения из базы данных при сохранении отношения?
ОБНОВЛЕНИЕ: Пример кода, мой метод назначения / обновления для экземпляра Broadcast
. Переменная словаря
поступает из веб-службы, а каналы
и программы
содержат каналы ошибок и программные объекты, индексированные идентификатором веб-службы. Ошибка возникает в строках self.program = program
и self.channel = channel
.
- (BOOL)assignWithDictionary:(NSDictionary *)dictionary channels:(NSDictionary *)channels programs:(NSDictionary *)programs {
// Add channel relationship
NSNumber *channelIdentifier = [dictionary objectForKey:@"channel_id"];
if (self.channel == nil || ![self.channel.identifier isEqualToNumber:channelIdentifier]) {
Channel *channel = [channels objectForKey:channelIdentifier];
if (channel == nil) {
NSLog(@"Broadcast %@ has invalid channel: %@", identifier, channelIdentifier);
return NO;
}
self.channel = channel;
}
// Same to add a program relationship
// ...
}
И мой запрос на получение каналов или списка программ:
- (NSDictionary *)itemsForEntity:(NSEntityDescription *)entity {
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSError *error = nil;
NSArray *itemsArray = nil;
request.entity = entity;
request.relationshipKeyPathsForPrefetching = [NSArray arrayWithObject:@"broadcasts", nil];
request.propertiesToFetch = [NSArray arrayWithObjects:@"identifier", @"version", nil];
itemsArray = [self.context executeFetchRequest:request error:&error];
NSAssert1(error == nil, @"Could not fetch the items from the database: %@", error);
{
NSMutableDictionary *items = [NSMutableDictionary dictionaryWithCapacity:itemsArray.count];
for (NSManagedObject *item in itemsArray) {
[items setObject:item forKey:[item valueForKey:@"identifier"]];
}
return [NSDictionary dictionaryWithDictionary:items];
}
}