如何在Realm中设置自动增量键?

时间:2014-10-08 08:33:05

标签: ios realm

我为每个ChatData对象都有一个唯一的msgid。

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

但每次我创建一个新对象时,我都要查询所有对象并获取最后一个msgid。

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

是否有一种有效的方法来替换此实现?

6 个答案:

答案 0 :(得分:52)

Realm没有自动增量行为,因此您需要自己管理。一个问题我鼓励您问问自己您的数据:

是否需要连续的,连续的整数ID?

如果没有,那么唯一的字符串主键可能就足够了。然后,您可以使用[[NSUUID UUID] UUIDString]之类的内容生成唯一的字符串ID。关于这一点的好处是,即使在多线程场景中,这些UUID也或多或少地保证是唯一的。

如果是这样,始终将最后一个数字保留在内存中可能更有效,因此每次生成新ID时都不需要查询。如果可能在多个线程中创建对象,请确保使nextPrimaryKey()函数具有线程安全性,否则它可能会生成相同的数字两次(或更多!)。

答案 1 :(得分:11)

您在Swift中使用此代码作为自动增量主键:

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

答案 2 :(得分:10)

Swift 2.0中的Autoincrement id Realm: 在类领域插入代码和对象写入使用

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
    }
}

在文件写入中使用:

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])
    })

答案 3 :(得分:2)

在Realm中,您需要自行管理auto-inc ID,因此有很多方法可以管理它。以下是其中一些。

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

每次添加记录时都会调用此方法。

答案 4 :(得分:0)

我在模型中使用了creationDate,所以我根据这个日期创建了一个 Unix timeStamp ,并将它用作我对象的primaryKey。

99.99%保证在我的情况下是唯一的 (因为时间戳精确到秒),但它可能取决于您的使用案例。 它不如UUID强大,但在很多情况下它足够了。

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
    }
}

答案 5 :(得分:0)

这基本上是在jpsim的回答中建议的,使用UUID生成唯一键。我们在插入之前进行查询以确保唯一性。这通常只会产生一个查询;在非常罕见的碰撞情况下,它会一直持续到找到唯一的ID。此解决方案是Realm类型的自然扩展,对于继承自Object的类是通用的。该类必须实现primaryKey并返回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)
    }
}