Создание уникального идентификатора для программы Core Data на iPhone - PullRequest
57 голосов
/ 29 августа 2009

У меня возникли проблемы с выяснением этих базовых данных. Как мне создать новую запись с уникальным идентификатором? В SQL я бы просто объявил одно поле как поле автоинкремента. Я не вижу ничего подобного здесь, но я мог бы что-то упустить. Я просто хочу автоматически увеличивать поле NSInteger, поэтому, когда я вручную добавлю элементы в базу данных, у меня будет некоторая форма ссылки на них.

Ответы [ 9 ]

145 голосов
/ 24 января 2010

Хотя я согласен с тем, что вы сказали, за основными данными стоит механизм идентификации. Идентификаторы действительно управляются Core-Data, но вы можете получить их с помощью:

NSManagedObjectID *moID = [managedObject objectID];

Для получения дополнительной информации см .: Руководство по программированию основных данных

28 голосов
/ 30 августа 2009

Это не так, как работает CoreData.

В CoreData вы создаете экземпляры сущностей. Каждый экземпляр уникален. Затем вы получаете и манипулируете экземплярами по мере необходимости. CoreData заботится о постоянстве для вас, в том числе уникально идентифицируя экземпляры.

Отойди от всего, что ты знаешь о традиционных реляционных базах данных.

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

10 голосов
/ 15 сентября 2012

Эта функция класса вернет следующий доступный номер для вашего свойства id (это должно быть целочисленное свойство).

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

Вы можете поместить эту функцию в свой подкласс NSManagedObject для объекта:

+(NSNumber *)nextAvailble:(NSString *)idKey forEntityName:(NSString *)entityName inContext:(NSManagedObjectContext *)context{


    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSManagedObjectContext *moc = context;
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:moc];

    [request setEntity:entity];
    // [request setFetchLimit:1];

    NSArray *propertiesArray = [[NSArray alloc] initWithObjects:idKey, nil];
    [request setPropertiesToFetch:propertiesArray];
    [propertiesArray release], propertiesArray = nil;

    NSSortDescriptor *indexSort = [[NSSortDescriptor alloc] initWithKey:idKey ascending:YES];
    NSArray *array = [[NSArray alloc] initWithObjects:indexSort, nil];
    [request setSortDescriptors:array];
    [array release], array = nil;
    [indexSort release], indexSort = nil;

    NSError *error = nil;
    NSArray *results = [moc executeFetchRequest:request error:&error];
    // NSSLog(@"Autoincrement fetch results: %@", results);
    NSManagedObject *maxIndexedObject = [results lastObject];
    [request release], request = nil;
    if (error) {
        NSLog(@"Error fetching index: %@\n%@", [error localizedDescription], [error userInfo]);
    }
    //NSAssert3(error == nil, @"Error fetching index: %@\n%@", [error localizedDescription], [error userInfo]);

    NSInteger myIndex = 1;
    if (maxIndexedObject) {
        myIndex = [[maxIndexedObject valueForKey:idKey] integerValue] + 1;
    }

    return [NSNumber numberWithInteger:myIndex];
}
6 голосов
/ 12 октября 2012

Вот три вида представления уникального идентификатора объекта CoreData:

NSManagedObjectID *taskID = [task objectID];
NSURL *taskUniqueURLKey = task.objectID.URIRepresentation;
NSString *taskUniqueStringKey = task.objectID.URIRepresentation.absoluteString;

!!!! Примечание: если вы хотите использовать указанный выше уникальный ключ в качестве индекса, убедитесь, что объект сохранен в контексте перед его использованием, иначе objectID будет временным идентификатором, который будет заменен позже (например, после сохранены). См. Яблочный документ класса NSManagedObjectID:

- (BOOL)isTemporaryID;    // indicates whether or not this ID will be replaced later, 
such as after a save operation (temporary IDs are assigned to newly inserted objects 
and replaced with permanent IDs when an object is written to a persistent store); most
 IDs return NO
6 голосов
/ 23 июня 2010

Взгляните на: [[NSProcessInfo processInfo] globallyUniqueString].

Apple Docs: глобальный идентификатор процесса. Идентификатор включает имя хоста, идентификатор процесса и метку времени, что гарантирует уникальность идентификатора для сети, что удобно, если вы не хотите, чтобы люди угадывали идентификатор.

2 голосов
/ 31 октября 2016

Обновление ответа @Lukasz в Swift:

static func nextAvailble(_ idKey: String, forEntityName entityName: String, inContext context: NSManagedObjectContext) -> Int {
    let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entityName)
    fetchRequest.propertiesToFetch = [idKey]
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: idKey, ascending: true)]

    do {
        let results = try context.fetch(fetchRequest)
        let lastObject = (results as! [NSManagedObject]).last

        guard lastObject != nil else {
            return 1
        }

        return lastObject?.value(forKey: idKey) as! Int + 1

    } catch let error as NSError {
        //handle error
    }

    return 1 
}
2 голосов
/ 17 июня 2010

Я думаю, что это будет полезно в таких условиях.

http://lists.apple.com/archives/cocoa-dev/2006/Jul/msg01801.html Мы можем получить maxExistingID. Так что мы можем увеличить это при сохранении нового элемента

2 голосов
/ 04 мая 2010

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

1 голос
/ 02 ноября 2016

Базовые данные используются для персистентной структуры, эта структура абстрагирует первичный ключ.

Каждый NSManagedObject имеет свой уникальный встроенный ключ, который доступен в его свойстве objectID.

Этот идентификатор внутренне используется для связи сущностей через свои отношения. Нет необходимости поддерживать собственный идентификатор в качестве первичного ключа, как вы привыкли делать в SQL.

Вы всегда можете получить идентификатор по NSManagedObject.objectID. и извлечение контекста объекта с использованием NSMananagedObjectContext.objectWithId

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...