web-dev-qa-db-fra.com

Création d'un identifiant unique pour un programme Core Data sur l'iPhone

J'ai un peu de mal à comprendre ce truc Core Data. Comment créer une nouvelle entrée avec un ID unique? En SQL, je déclarerais simplement un champ comme un champ d'auto-incrémentation. Je ne vois rien de tel ici, mais je pourrais simplement manquer quelque chose. Je veux juste un champ NSInteger à incrémentation automatique, donc quand j'ajouter manuellement des éléments à la base de données, j'aurai une forme de référence à eux.

57
user165411

Bien que je sois d'accord avec ce que vous avez dit, il existe un mécanisme d'identification derrière les données de base. Les identifiants sont en effet gérés par Core-Data mais vous pouvez les récupérer avec:

NSManagedObjectID *moID = [managedObject objectID];

Pour plus d'informations, voir: Core Data Programming Guide

146
user142764

Ce n'est pas ainsi que fonctionne CoreData.

Dans CoreData, vous créez des instances d'entités. Chaque instance est unique. Vous récupérez et manipulez ensuite les instances selon vos besoins. CoreData s'occupe de la persistance pour vous, y compris l'identification unique des instances.

Éloignez-vous de tout ce que vous savez sur les bases de données relationnelles traditionnelles.

CoreData est une technologie extrêmement puissante qui offre des fonctionnalités bien au-delà de la simple base de données comme la persistance. Cela vous fera économiser de nombreuses lignes de code et fonctionnera extrêmement bien si vous l'adoptez.

28
bbum

Cette fonction de classe renverra prochain numéro disponible pour votre propriété id (il doit s'agir d'une propriété entière).

Je l'appelle générateur de valeur à incrémentation automatique. Je suis toujours d'accord avec les autres pour dire qu'il y a objectID pour cela, mais parfois vous avez juste besoin d'un numéro.

Vous pouvez placer cette fonction dans votre sous-classe NSManagedObject pour l'entité:

+(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];
}
10
Lukasz

Voici trois types de représentation d'ID unique de l'objet CoreData:

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

!!!! Remarque: si vous souhaitez utiliser la clé unique ci-dessus comme index, assurez-vous que l'objet est enregistré dans le contexte avant de l'utiliser, ou l'ID d'objet serait un identifiant temporaire, qui sera remplacé plus tard (par exemple après l'enregistrement). Voir le document Apple Apple de la classe 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
flypig

Jeter un coup d'œil à: [[NSProcessInfo processInfo] globallyUniqueString].

Documents Apple: identifiant global du processus. L'ID comprend le nom d'hôte, l'ID de processus et un horodatage, ce qui garantit que l'ID est unique pour le réseau, ce qui est pratique si vous ne voulez pas que les gens le devinent.

6
yooj

Que se passe-t-il si nous voulons synchroniser avec une base de données distante qui nécessite des identifiants auto-incrémentés pour des lignes de données uniques? Existe-t-il un moyen d'implémenter les identifiants auto-incrémentés si nous en avons besoin? Je comprends que ce n'est pas requis pour les données de base, mais je dois importer des données à partir d'une base de données distante, puis les télécharger à nouveau et m'assurer que les identifiants sont intacts.

2
marchinram

Mise à jour de la réponse @Lukasz dans 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
Vlad Fedoseev

je pense que ce sera utile dans de telles conditions.

http://lists.Apple.com/archives/cocoa-dev/2006/Jul/msg01801.html Nous pouvons obtenir maxExistingID. SO nous pouvons incrémenter cela lors de l'enregistrement d'un nouvel élément

2
S.P.

Les données de base sont utilisées pour le cadre de persistance, ce cadre résume la clé primaire.

Chaque NSManagedObject a sa propre clé unique intégrée qui est disponible dans sa propriété objectID.

Cet identifiant est utilisé en interne pour lier des entités sur ses relations. Il n'est pas nécessaire de conserver son propre identifiant comme clé primaire comme vous le faites habituellement en SQL.

Vous pouvez toujours obtenir l'id par NSManagedObject.objectID. et récupération du contexte d'objet à l'aide de NSMananagedObjectContext.objectWithId

1
AmitChauhan