【问题标题】:composite primary key realm/swift复合主键领域/swift
【发布时间】:2025-10-14 00:25:01
【问题描述】:

我是 swift 和领域的新手。我想制作一个复合主键,当我尝试这样的事情时:

class DbLocation : Object {
 dynamic var id = 0
 dynamic var tourId = 0

 dynamic var uuid : String  {
    return "\(id)\(tourId)"
 }

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

我收到此错误: '对象'DbLocation'上不存在主键属性'uuid'

任何人都可以通过一个示例来帮助我如何创建复合主键?

【问题讨论】:

    标签: ios swift realm


    【解决方案1】:

    对于1.0.1+的Realm:

    class DbLocation: Object{
        dynamic var id = 0
        dynamic var tourId = 0
        dynamic var compoundKey = ""
    
        override static func primaryKey() -> String? {
            return "compoundKey"
        }
    
        func setup(id: Int, tourId: Int){
            self.id = id
            self.tourId = tourId
            self.compoundKey = compoundKeyValue()
        }
    
        func compoundKeyValue() -> String {
            return "\(id)\(tourId)"
        }
    }
    

    使用示例:

    let location = DbLocation()
    location.setup(id: 0, tourId: 1) 
    print(location.compoundKey) // "01"
    

    当然,您可以在idtourId 上使用各种didSet 侦听器,以确保每次更改值时都正确重写compoundKey。

    对于pre-1.0.1的Realm:

    class DbLocation: Object {
        dynamic var id = 0
        dynamic var tourId = 0
    
        func setCompoundID(id: Int) {
            self.id = id
            compoundKey = compoundKeyValue()
        }
    
        func setCompoundTourId(tourId: Int) {
            self.tourId = tourId
            compoundKey = compoundKeyValue()
        }
    
        dynamic lazy var compoundKey: String = self.compoundKeyValue()
    
        override static func primaryKey() -> String? {
            return "compoundKey"
        }
    
        func compoundKeyValue() -> String {
            return "\(id)\(tourId)"
        }
    }
    

    自定义设置器确保 CompoundKey 始终更新,惰性关键字确保您第一次访问它时,它将派生自您已经设置的内容。

    this thread 中了解有关此主题的更多信息,该问题已在此讨论过。

    【讨论】:

    • 如果我们这样声明复合键变量:dynamic lazy var fullName: String = "(self.id)-(self.tourId)" 那么这有什么问题呢?提前致谢
    • Swift 惰性属性被明确禁止,除非它们被忽略。我们现在如何解决这个问题@Michal?
    • 由于未捕获的异常“RLMException”而导致应用程序终止,原因:Realm Swift 对象类上不允许使用“惰性托管属性”。要么将该属性添加到忽略的属性列表中,要么使其成为非惰性属性。'
    • @BlackTiger 唯一的方法是仅通过setCompoundID(id: Int)setCompoundTourId(tourId: Int) 函数将写入引导到idtourId,因此您肯定知道最新的compoundKey写了,那么你就可以拯救这个境界了。此外,如果您选择以这种方式实现,那么您可以删除 lazy 关键字和 self.compoundKeyValue()
    • 嗨,我收到“由于未捕获的异常 'RLMException' 导致应用程序终止,原因:Realm Swift 对象类上不允许使用惰性托管属性 'compoundKey'。要么将该属性添加到忽略属性列表或使其非惰性。”在惰性复合键上。
    【解决方案2】:

    简单地创建一个新属性,其值设置为您希望作为复合主键的其他感兴趣的属性。

    class DbLocation: Object {
                dynamic var id = 0
                dynamic var tourId = 0
                dynamic var compoundKey: String? = ""
    
            override static func primaryKey() -> String? {
                    return "compoundKey"
                }
            }
        let location = DbLocation()
        location.tourId = 1
        location.id = 5
        location.compoundKey = "\(id) \(tourId)"
    

    【讨论】:

    • 抱歉,老兄,但我们已经知道解决方法(如您的回答),但是关于复合键的本机支持的讨论已经进行了一段时间,并且在此处跟踪问题:github.com/realm/realm-cocoa/issues/3453
    【解决方案3】:

    对于最新版本的 Swift 和 Realm,我会做这样的事情。

    dynamic private var compoundKey: String = ""
    
    required convenience init?(map: Map) {
      self.init()
      if let firstValue = map.JSON["firstValue"] as? String,
        let secondValue = map.JSON["secondValue"] as? Int {
        compoundKey = firstValue + "|someStringToDistinguish|" + "\(secondValue)"
      }
    }
    

    【讨论】: