2015-11-19 3 views
0

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

// Check for existing Object 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Object" inManagedObjectContext:managedObjectContext]]; 
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"name == %@", objectName]]; 
[fetchRequest setFetchLimit:1]; 

NSError *error = nil; 
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
if (results == nil) { 
    NSAssert(NO, @"Error executing fetch: %@\n%@", [error localizedDescription], [error userInfo]); 
} 

Object *object = [results lastObject]; 

if (object == nil) { 
    // Create new object 
    object = [NSEntityDescription insertNewObjectForEntityForName:@"Object" inManagedObjectContext:managedObjectContext]; 
    object.name = objectName; 
} 


// Check for existing Other 
fetchRequest = [[NSFetchRequest alloc] init]; 
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Other" inManagedObjectContext:managedObjectContext]]; 
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"name == %@", otherName]]; 
[fetchRequest setFetchLimit:1]; 

results = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
if (results == nil) { 
    NSAssert(NO, @"Error executing fetch: %@\n%@", [error localizedDescription], [error userInfo]); 
} 

Other *other = [results lastObject]; 

if (other == nil) { 
    // Create new Other 
    other = [NSEntityDescription insertNewObjectForEntityForName:@"Other" inManagedObjectContext:managedObjectContext]; 
    other.name = otherName; 
} 


// Finally 
[object addOtherObject:other]; // A many-to-many relationship 

if (![managedObjectContext save:&error]) { 
    NSAssert(NO, @"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
} 

Все это, конечно, внутри петли, оно кажется ужасно неэффективным.

+0

Посмотрите на магическую запись и Mogenerator. Core Data полон код шаблона, библиотеки библиотек удаляют большую часть из них – Antzi

+0

Это все о наборах. Вместо того, чтобы извлекать одну сущность за раз в цикле, выберите все сразу. Затем вы можете выяснить, какие объекты не существуют в результатах и ​​создать их. – Avi

ответ

0

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

+ (NSString *)entityName; 

+ (instancetype)newEntityInContext:(ManagedObjectContext *)context; 
+ (instancetype)newEntityInContext:(ManagedObjectContext *)context properties:(NSDictionary *)properties; 

+ (NSArray *)entitiesWithPredicate:(NSPredicate *)predicate inContext:(RoundsManagedObjectContext *)context; 
+ (NSArray *)entitiesWithPredicate:(NSPredicate *)predicate 
         sortedBy:(NSArray *)sortDescriptors 
        inContext:(ManagedObjectContext *)context; 

+ (NSArray *)entitiesWithProperties:(NSDictionary *)properties inContext:(ManagedObjectContext *)context; 

+ (NSInteger)countOfEntitiesWithPredicate:(NSPredicate *)predicate inContext:(ManagedObjectContext *)context; 

Я оставляю вам, чтобы увидеть, как они заботятся о шаблонном создании запросов и т.п. выборки. Это действительно делает ваш код, который на самом деле использует данные ядра, чтобы быть более читаемыми.

Теперь, чтобы говорить об эффективности ведения тех неправдоподобных в цикле:

не делать. То есть, не делайте отдельные выборки. Вместо этого, соберите objectName s в массив и выберете сразу все связанные объекты. Предполагая, что вы реализуете методы, аналогичные тем, что я написал выше, вы можете иметь псевдокод, который выглядит примерно так:

NSArray *objectNames = ...; 
NSArray *otherNames = ...; 

NSManagedObjectContext *context = ...; 

NSArray *existingObjects = [Object entitiesWithPredicate:[NSPredicate predicateWithFormat:@"name IN %@", objectNames]; 
NSArray *existingOthers = [Other entitiesWithPredicate:[NSPredicate predicateWithFormat:@"name IN %@", otherNames]; 

NSArray *missingObjectNames = [objectNames removeObjects:[existingObjects valueForKeyPath:@"name"]]; 

for (NSString *name in missingObjectNames) { 
    Object *object = [Object newEntityInContext:context]; 
    object.name = name; 

    // Do stuff with Other objects here. 
} 
+0

Примечание: я не дал код для 'Other', потому что немного непонятно, как вы определяете, какое' otherName' идет, с каким 'Object'. Надеюсь, я дал достаточно оснований, чтобы выяснить, что вам нужно добавить. – Avi