如何在Swift中创建List <anyrealmobject>?

时间:2017-10-08 01:47:05

标签: ios swift realm

好的,首先,我知道没有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)(
   }
}

???的内容是我要问的问题。如果有更好的方法可以做到这一点我全都耳朵。我认为我的方法还可以,我不知道如何填补这些空白。

2 个答案:

答案 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;解决方案,但这个答案提供了一定程度的通用性,可以通过一个主要基础对象访问许多不同的对象类型。