好的,首先,我知道没有AnyRealmObject
之类的东西。
但我需要有一些行为就像一个领域List
,除了可以将任何类型的领域Object
添加到列表中 - 他们不会所有都必须是同一类型。
目前,我有这样的事情:
enter code here
class Family: Object {
var pets: List<Pet>
}
class Pet: Object {
var dog: Dog?
var cat: Cat?
var rabbit: Rabbit?
}
目前,如果我想添加Bird
,我必须修改Pet
对象。我不想继续修改那个课程。
我真正想做的是:
class Family: Object {
var pets: List<Object>
}
或者,也许,定义一个Pet
协议,该协议必须是一个对象,并且var pets: List<Pet>
关键是,我想要一个数据集,它可以包含我传入它的任何Realm对象。数据库的唯一要求是对象必须是Realm对象。
现在,由于Realm不允许这样做,我怎么能这样做呢?我正在考虑创建类似Realm ObjectReference
类的东西:
class ObjectReference: Object {
var className: String
var primaryKeyValue: String
public init(with object: Object) {
className = ???
primaryKeyValue = ???
}
public func object() -> Object? {
guard let realm = realm else { return nil }
var type = ???
var primaryKey: AnyObject = ???
return realm.object(ofType: type, forPrimaryKey: primaryKey)(
}
}
???
的内容是我要问的问题。如果有更好的方法可以做到这一点我全都耳朵。我认为我的方法还可以,我不知道如何填补这些空白。
答案 0 :(得分:1)
(我假设您正在编写一个应用程序,并且您提供的代码示例和问题的上下文是应用程序代码,而不是创建库。)
鉴于Realm目前的局限性,您的方法似乎是一个不错的方法;我无法想到任何更好的东西。您可以使用NSClassFromString()
将className
字符串转换为可与object(ofType:...)
API一起使用的Swift元类对象:
public func object() -> Object? {
let applicationName = // (application name goes here)
guard let realm = realm else { return nil }
guard let type = NSClassFromString("\(applicationName).\(className)") as? Object.Type else {
print("Error: \(className) isn't the name of a Realm class.")
return nil
}
var primaryKey: String = primaryKeyValue
return realm.object(ofType: type, forPrimaryKey: primaryKey)(
}
我的建议是保持简单,只使用字符串作为主键。如果您确实需要能够使用任意类型作为主键,您可以查看我们的dynamic API,了解如何提取给定对象的主键值。 (请注意,尽管此API在技术上是公共API,但我们通常不会为它提供支持,除非键入的API不合适,否则我们也不鼓励使用它。)
将来,我们希望为子类化和多态性提供增强的支持。根据此功能的设计方式,它可能允许我们引入API以允许将父对象类型的子类插入到列表中(尽管它构成了own problems)。
答案 1 :(得分:0)
这可能不是一个完整的答案,但可以提供一些方向。如果我正确地阅读问题(带注释),目标是有一个更通用的对象,可以作为其他对象的基类。
虽然这不是直接可行的 - 即一个NSObject是NSView,NSString等的基础,这个怎么样......
让我们定义一些Realm对象
class BookClass: Object {
@objc dynamic var author = ""
}
class CardClass: Object {
@objc dynamic var team = ""
}
class MugClass: Object {
@objc dynamic var liters = ""
}
然后是一个名为Inventory Item Class的基础领域对象,它将代表它们
class InvItemClass: Object {
@objc dynamic var name = ""
@objc dynamic var image = ""
@objc dynamic var itemType = ""
@objc dynamic var book: BookClass?
@objc dynamic var mug: MugClass?
@objc dynamic var card: CardClass?
}
然后假设我们想要存储一些书籍以及我们的杯子和卡片(来自评论)
let book2001 = BookClass()
book2001.author = "Clarke"
let bookIRobot = BookClass()
bookIRobot.author = "Asimov"
let item0 = InvItemClass()
item0.name = "2001: A Space Odyssey"
item0.image = "Pic of Hal"
item0.itemType = "Book"
item0.book = book2001
let item1 = InvItemClass()
item1.name = "I, Robot"
item1.image = "Robot image"
item1.itemType = "Book"
item1.book = bookIRobot
do {
let realm = try Realm()
try! realm.write {
realm.add(item0)
realm.add(item1)
}
} catch let error as NSError {
print(error.localizedDescription)
}
从这里开始,我们可以将所有库存物品对象作为一组对象(根据问题)加载,并根据其类型采取措施;例如,如果想要加载所有项目并打印出那些书籍。
do {
let realm = try Realm()
let items = realm.objects(InvItemClass.self)
for item in items {
switch item.itemType {
case "Book":
let book = item.book
print(book?.author as! String)
case "Mug":
return
default:
return
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
目前还没有一个通用的“一个领域”对象适合所有&#39;解决方案,但这个答案提供了一定程度的通用性,可以通过一个主要基础对象访问许多不同的对象类型。