web-dev-qa-db-fra.com

Comment définir une clé d'incrémentation automatique dans Realm?

J'ai un unique msgid pour chaque objet ChatData.

@interface ChatData : RLMObject
@property NSInteger msgid;
....
@end

Mais chaque fois que je crée un nouvel objet, je dois interroger tous les objets et obtenir le dernier msgid.

RLMArray *all = [[ChatData allObjects] arraySortedByProperty:@"msgid" ascending:YES];
ChatData *last = [all lastObject];
ChatData *newData = [[ChataData alloc]init];
newData.msgid = last.msgid+1;

Existe-t-il un moyen efficace de remplacer cette implémentation?

33
drinking

Realm n'a pas de comportement d'incrémentation automatique, vous devrez donc le gérer vous-même. Une question que je vous encourage à vous poser à propos de vos données:

Est-il nécessaire d'avoir des ID entiers séquentiels, contigus?

Sinon, une clé primaire unique en chaîne pourrait suffire. Ensuite, vous pouvez utiliser quelque chose comme [[NSUUID UUID] UUIDString] pour générer des ID de chaîne uniques. La bonne chose à propos de cela est que ces UUID sont plus ou moins garantis d'être uniques, même dans des scénarios multithread.

Si tel est le cas, il serait peut-être plus efficace de toujours conserver le dernier numéro en mémoire, de sorte que les requêtes ne soient plus nécessaires à chaque génération d'un nouvel ID. Si des objets peuvent être créés dans plusieurs threads, assurez-vous que votre fonction nextPrimaryKey() est thread-safe, sinon elle pourrait générer le même nombre deux fois (ou plus!).

51
jpsim

Vous utilisez ce code pour la clé primaire incrémentielle automatique dans Swift: 

var myvalue = realm.objects(ChatData).map{$0.id}.maxElement() ?? 0
myvalue = myvalue + 1
9
Kirit Modi

Autoincrement id Realm dans Swift 2.0: Insérer du code dans la classe et l'utilisation de l'objet en écriture

import Foundation
import RealmSwift

class Roteiro: Object {

dynamic var id = 0
dynamic var Titulo = ""
dynamic var Observacao = ""
dynamic var status = false
dynamic var cadastrado_dt = NSDate()

override static func primaryKey() -> String? {
    return "id"
}

//Incrementa ID
func IncrementaID() -> Int{
    let realm = try! Realm()
    if let retNext = realm.objects(Roteiro.self).sorted(byKeyPath: "id").first?.id {
        return retNext + 1
    }else{
        return 1
    }
}

utilisation en écriture de fichier:

let Roteiro_Add = Roteiro()
    //increment auto id
    Roteiro_Add.id = Roteiro_Add.IncrementaID()

    Roteiro_Add.Titulo = TituloDest
    Roteiro_Add.Observacao = Observacao
    Roteiro_Add.status = false


    let realm = try! Realm()
    try! realm.write({ () -> Void in
        realm.add([Roteiro_Add])
    })
9
Pablo Ruan

Dans Realm, vous devez gérer auto-inc ID lui-même. Il existe donc de nombreuses façons de le gérer. En voici quelques unes.

 func incrementID() -> Int {
        let realm = try! Realm()
        return (realm.objects(Person.self).max(ofProperty: "id") as Int? ?? 0) + 1
    }

appelez cette méthode à chaque fois que vous ajoutez un enregistrement.

2
Govaadiyo

C’est essentiellement ce que suggère la réponse de jpsim, en utilisant UUID pour générer des clés uniques. Nous interrogeons avant d'insérer pour assurer l'unicité. Le plus souvent, cela ne génère qu'une requête. dans le cas très rare d'une collision, il continuera jusqu'à ce qu'il trouve un identifiant unique. Cette solution est une extension naturelle du type Realm et est générique pour les classes héritées de Object. La classe doit implémenter primaryKey et renvoyer le nom d'une propriété String.

extension Realm {

    func createAutoUnique<T: Object>(_ type: T.Type) -> T {

        guard let primaryKey = T.primaryKey() else {

            fatalError("createAutoUnique requires that \(T.self) implements primaryKey()")
        }

        var id: String

        var existing: T? = nil

        repeat {

            id = UUID().uuidString

            existing = object(ofType: type, forPrimaryKey: id)

        } while (existing != nil)

        let value = [
            primaryKey: id
        ]

        return create(type, value: value, update: false)
    }
}
0
Patrick Goley

J'ai utilisé creationDate dans mon modèle, j'ai donc créé un Unix timeStamp basé sur cette date et je l'ai utilisé comme primaryKey de mon objet.

Elle est garantie à 99,99% d'être unique dans mon cas (parce que l'horodatage est précis à la seconde près), mais cela peut dépendre de votre cas d'utilisation . Il est moins robuste qu'un UUID, mais dans de nombreux cas, il suffit .

extension NSDate {

    /** Returns a NSDate instance from a time stamp */
    convenience init(timeStamp: Double) {
        self.init(timeIntervalSince1970: timeStamp)
    }
}


extension Double {

    /** Returns a timeStamp from a NSDate instance */
    static func timeStampFromDate(date: NSDate) -> Double {    
        return date.timeIntervalSince1970
    }
}
0
Frédéric Adda