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

Isu*_*uru 6 dao data-access-layer realm ios swift

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

我遇到了这个类似的问题,并试图建立我在那里找到的信息.在那里讨论的方法是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()
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个包含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?
}
Run Code Online (Sandbox Code Playgroud)

最后,我创建了另一个调用ChatHelper所有协议方法的类.

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
    }

}
Run Code Online (Sandbox Code Playgroud)

这似乎比在VC和东西上遍布所有数据库相关代码更好.但我还是有些疑惑.

例如,假设我需要获得聊天的所有参与者,现在我必须在ChatHelper课堂上调用该方法.如果我想简单地获得聊天标题,我会调用对象本身的title属性Chat.看起来不是一个非常统一的界面.我是否应该在帮助程序中包含所有属性的getter和setter.因此Chat永远不会直接调用该对象(除了可能创建实例).

要么

我应该使Chat对象本身符合ChatDAOProtocol协议吗?所以所有便利方法以及属性都可以直接从Chat对象直接访问?

还是有比这两者更好的方法?

TiM*_*TiM 3

这是一个相当棘手的问题,因为它实际上取决于您想要从与 Realm 的直接交互中抽象出多少东西,以及您想要在多大程度上对 Realm 的性能做出妥协。

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

但你绝对需要小心的一件事是,以一种非常低效地利用 Realm 的方式抽象逻辑。

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

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