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

Posted

技术标签:

【中文标题】如何在 Realm 中设置自动增量键?【英文标题】:How do I set a auto increment key in Realm? 【发布时间】:2014-12-02 20:23:31 【问题描述】:

每个 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;

有没有一种有效的方法来替换这个实现?

【问题讨论】:

【参考方案1】:

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

是否必须有连续的、连续的整数 ID?

如果不是,那么唯一的字符串主键可能就足够了。然后你可以使用[[NSUUID UUID] UUIDString] 之类的东西来生成唯一的字符串ID。这样做的好处是,这些 UUID 或多或少保证是唯一的,即使在多线程场景中也是如此。

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

【讨论】:

是否有计划向 Realm 添加自动增量行为? 是的,该功能即将推出,但我没有给你的时间表。 把这个放在+defaultPropertyValues 字典里没问题吧?我指的是[[NSUUID UUID] UUIDString] 对于 Swift 使用这个NSUUID().UUIDString checkout github.com/realm/realm-cocoa/issues/2591#issuecomment-170259579 如果有人关心 Realm 自动增量功能【参考方案2】:

您正在将此代码用于 Swift 中的自动增量主键:

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

【讨论】:

应用程序因“插入对象后无法更改主键”错误而终止。更新主键的任何替代方法? 很好的解决方案。像魅力一样工作。谢谢你:) func nextId() -> Int return (realm?.objects(MyRealmObject.self).map$0.id.max() ?? 0) + 1 【参考方案3】:

Swift 2.0 中的自动增量 id 领域: 在类领域插入代码和对象写入使用

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

【讨论】:

谢谢兄弟 :) 又快又好! 是的,多线程读写可能存在一些问题。这可能需要一些额外的过程。 if let retNext = realm.objects(Roteiro.self).sorted(byKeyPath: "id").first?.id 这应该是最后一项,例如 if let retNext = realm.objects(Ordernew .self).sorted(byKeyPath: "id").last?.id 【参考方案4】:

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

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

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

【讨论】:

我收到此错误“插入对象后无法更改主键”@Tofaani Kaanudo【参考方案5】:

我在我的模型中使用了 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
    

【讨论】:

【参考方案6】:

这基本上是 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)
    

【讨论】:

以上是关于如何在 Realm 中设置自动增量键?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift for Realm 模型中设置主键

如何在postgresql中设置与id不同的自动增量字段

hibernate - 如何在 mysql 和 oracle 数据库中设置自动增量?

如何在 Realm 中设置 NSPredicate 以找到 totalPrice > X?

在迁移 laravel 5.1 中设置自动增量字段从 1000 开始

如何使用 Swift 中的自动生成键从情节提要中设置的 UITextView 中检索文本?