ios - 如何使用 Realm 编写更好的数据访问层

标签 ios swift realm dao data-access-layer

我一直在几个小项目中使用 Realm,我非常喜欢它。我希望继续在更大的项目中使用它,并且我正在寻找更好的数据访问层结构。

我遇到了类似的 question并尝试建立我在那里找到的信息。那里讨论的方法是 DAO 模式,所以我试了一下。

这是我的模型类。

class Chat: Object {
    dynamic var id: String = ""
    dynamic var createdAt: Date = Date()
    dynamic var creatorId: String = ""
    dynamic var title: String?
    let chatMessages = List<ChatMessage>()

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

    convenience init(fromJSON json: JSON) {
        self.init()
        // ...
    }
}

然后我创建了一个 ChatDAOProtocol 来保存所有方便的辅助方法。

protocol ChatDAOProtocol {
    func addMessage(_ message: ChatMessage)
    func getChatThumbnail() -> UIImage
    func getParticipants(includingMe: Bool) -> [Participant]?
    static func getChat(fromId id: String) -> Chat?
    static func getChat(fromCreatorId id: String) -> Chat?
}

最后,我创建了另一个名为 ChatHelper 的类,它实现了所有这些协议(protocol)方法。

class ChatHelper: ChatDAOProtocol {
    func addMessage(_ message: ChatMessage) {

    }

    func getChatThumbnail() -> UIImage {
        return UIImage()
    }

    func getParticipants(includingMe: Bool) -> [Participant]? {
        return nil
    }

    static func getChat(fromId id: String) -> Chat? {
        return nil
    }

    static func getChat(fromCreatorId id: String) -> Chat? {
        return nil
    }

}

这似乎比在 VC 和其他东西上散布所有与数据库相关的代码要好。但我还是有些疑惑。

例如,假设我需要获取聊天的所有参与者,现在我必须调用 ChatHelper 类上的方法。如果我只想获得聊天标题,我会调用 Chat 对象本身的 title 属性。看起来不是很统一的界面。我是否也应该在助手中包含所有属性的 getter 和 setter。所以永远不会直接调用 Chat 对象(除非可能创建一个实例)。

或者

我应该让 Chat 对象本身符合 ChatDAOProtocol 协议(protocol)吗?那么所有的便捷方法和属性都可以直接从 Chat 对象直接访问吗?

或者有比这两种更好的方法吗?

最佳答案

这是一个非常棘手的问题,因为它实际上取决于您希望从与 Realm 的直接交互中抽象出多少,以及您希望在 Realm 的性能方面做出多少妥协。

就我个人而言,我认为如果您抽象出查询和写入逻辑,但仍然直接从 Realm 模型对象中读取,那很好。如果您移动到另一个基于对象的数据库(如 Core Data),那么当您重构父类时,这些对象属于其他对象(例如,RLMObjectNSManagedObject) ,您的业务逻辑从这些对象中读取的方式不会改变。

但您绝对需要注意的一件事是以一种非常低效地利用 Realm 的方式抽象逻辑。

我能看到的主要示例是在您的 getParticipants 方法中,您正在返回一个标准的 Swift 数组。将 Realm Results 对象转换成这样会导致内存中的每个对象分页(而不是根据请求延迟加载),因此您将失去很多 Realm 性能优势。但由于 Results 对象的行为类似于标准数组,如果您直接返回一个对象,则无需更改业务逻辑。

另一个考虑因素:如果您要更新一批对象的单个属性,最好确保所有对象都在单个写入事务中更新,而不是帮助程序类在每个内部打开一个写入事务调用辅助方法的时间。

关于ios - 如何使用 Realm 编写更好的数据访问层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41975550/

相关文章:

ios - 滚动到 collectionView 的底部不起作用

ios - 在 Swift MVC 中保存 TableView 数据

iOS7 静默推送通知不起作用

ios - 模拟器与物理设备 : NavigationLink broken after one use

swift - 如何在 Swift 中处理多重继承?

ios - Realm.io 和复合主键

ios - UIAlertView 改变 UITabbar item 选中的颜色

ios - UICollectionViewController 单元格在点击或滚动时消失

android - "between"两个日期对象的查询在 Realm 中返回错误的输出

swift - 在 Swift 中使 Realm Loop 通用且可重用