我创建了一个Realm对象,该对象需要存储一个枚举值。为此,我使用方法outlined in this question,该方法涉及声明类型为String的私有属性,然后声明类型为Enum的另一个属性,该属性使用getter和setter设置/读取私有属性。
为了便于参考,下面是该代码:
@objcMembers
class PlaylistRealmObject: Object {
dynamic var id: String = UUID().uuidString
dynamic var created: Date = Date()
dynamic var title: String = ""
private dynamic var revisionTypeRaw: String = RevisionType.noReminder.rawValue
var revisionType: RevisionType {
get { return RevisionType(rawValue: revisionTypeRaw)! }
set { revisionTypeRaw = newValue.rawValue }
}
let reminders = List<ReminderRealmObject>()
let cardsInPlaylist = List<CardRealmObject>()
override static func primaryKey() -> String? {
return "id"
}
}
但是我注意到,如果我在类声明中添加了一个便利的初始化(以便于初始化对象变得更容易),我最终得到的对象的versionType属性将采用该类中声明的默认值,而不是版本使用便捷初始化传递给类的类型值。
这是带有方便初始化的类声明
@objcMembers
class PlaylistRealmObject: Object {
dynamic var id: String = UUID().uuidString
dynamic var created: Date = Date()
dynamic var title: String = ""
private dynamic var revisionTypeRaw: String = RevisionType.noReminder.rawValue
var revisionType: RevisionType {
get { return RevisionType(rawValue: revisionTypeRaw)! }
set { revisionTypeRaw = newValue.rawValue }
}
let reminders = List<ReminderRealmObject>()
let cardsInPlaylist = List<CardRealmObject>()
convenience init(title: String, revisionType: RevisionType) {
self.init()
self.title = title
self.revisionType = revisionType
}
override static func primaryKey() -> String? {
return "id"
}
}
而且-使事情更加困惑-如果我只是从versionTypeRaw属性中删除单词“ private”,那么一切都很好!
我很困惑。 1)为什么添加一个便利初始化有这个效果? 2)为什么将财产设为“公开”可以解决问题?
我创建了一个演示Xcode项目来说明问题,并在任何人需要时可以共享。
更新:
我发现了问题。它与init的方便无关。我根据Realm文档在类顶部使用
@objcMembers
:https://realm.io/docs/swift/latest/#property-attributes如果将其删除并将
@objc
放在private
关键字的前面,则一切正常。我想问题是:什么解释了这种行为? 最佳答案
这是一个很好的问题,但是我认为问题出在代码的其他地方。让我们测试一下。
我创建了一个TestClass,它具有一个Realm管理的公共可见变量,名称,以及一个非托管的公共变量visibleVar,后者由Realm管理的私有变量privateVar支持。我还为每个问题提供了一个方便的初始化。重要的部分是将privateVar设置为字符串“占位符”,因此我们需要查看它是否被覆盖。
class TestClass: Object {
@objc dynamic var name = ""
@objc private dynamic var privateVar = "placeholder"
var visibleVar: String {
get {
return self.privateVar
}
set {
self.privateVar = newValue
}
}
convenience init(aName: String, aString: String) {
self.init()
self.name = aName
self.visibleVar = aString
}
}
然后,我们创建两个实例并将其保存在Realm中
let a = TestClass(aName: "some name", aString: "some string")
let b = TestClass(aName: "another name", aString: "another string")
realm.add(a)
realm.add(b)
然后执行一个按钮操作,以从Realm加载两个对象并打印它们。
let testResults = realm.objects(TestClass.self)
for test in testResults {
print(test.name, test.visibleVar)
}
和输出:
some name some string
another name another string
因此,在这种情况下,创建实例时将正确覆盖默认值“ placeholder”。
编辑:
更多信息。
通过使用@objMembers定义整个类,它会将您的属性公开给Objective-C,但随后再次将其隐藏。因此该属性不会暴露给ObjC。要扭转这种隐藏状态,您必须明确地说出@objc。因此,更好的做法是使用@objc动态定义每行的托管领域属性。