Найти или создать уникальный объект Core Data

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

Cheers,
ЕР

+(id)uniqueEntityfForName:(NSString *)name 
                withValue:(id)value 
                   forKey:(NSString *)key
   inManagedObjectContext:(NSManagedObjectContext *)context {

    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];    
    request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:context];
    request.predicate = [NSPredicate predicateWithFormat:[key stringByAppendingString:@" == %@"], value];
    NSArray *result = [context executeFetchRequest:request error:nil];

    id entity = [result lastObject];
    if (entity == nil) {
        entity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
        [entity setValue:value forKey:key];
    } else {
        entity = [result lastObject];
    }

    return entity;
}

Я использую этот метод следующим образом:

SomeEntity *entity = [CDUtils uniqueEntityfForName:@"SomeEntity" withValue:@"foo" forKey:@"bar" inManagedObjectContext:context];

Ответы

Ответ 1

Довольно стандартный. Мои основные объекты данных имеют множество методов, таких как [aStudent enrollmentForId:(long long)idValue createIfMissing:YES].

Я также хотел бы подключить mogenerator, что устраняет боль от Core Data. Помимо всего прочего, он генерирует метод factory для каждого запроса выборки, определенного в модели данных. Поэтому создание предиката выборки в модели, например,

штук: thingyId == $forThingyId

дает метод сопоставления классов:

+(NSArray *)fetchThingies:(NSManagedObjectContext *)moc forThingyId:(id)thingyId

... который делает первую половину того, что вы там написали. Обертка, подобная

-(Thingy*)thingyForIdValue:(long long)thingyId

является тривиальным для записи, в любом классе содержится ваш managedObjectContext (например, "родительский" объект или делегат приложения или что-то еще.)

Ответ 2

Более гибкое решение - использовать Blocks, чтобы вызывающий мог обрабатывать 3 ситуации при сравнении двух списков.

  • Соответствующие наборы
  • Непревзойденные наборы хостов
  • Локальные непревзойденные наборы

Поэтому нет необходимости создавать подобные функции при вставке в виде синхронизации или добавления в хранилище данных.

typedef void (^objectOperationBlock)(NSManagedObjectContext *context,
                                 NSDictionary *hostObjectData,
                                 NSManagedObject *localManagedObject);

- (void) insertUniquely:(NSArray *)rawDataArray 
                 entity:(NSString *)entity 
           matchedBlock:(objectOperationBlock)matchedOperation
     hostUnmatchedBlock:(objectOperationBlock)hostUnmatchedOperation
    localUnmatchedBlock:(objectOperationBlock)localUnmatchedOperation
                  error:(NSError **)outError;

Полную реализацию можно найти здесь: http://emplementation.blogspot.com/2011/12/importing-data-into-core-data-while.html