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

我一直在一些小项目中使用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() 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类,它实现了所有这些协议方法。

 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协议吗? 所以所有便捷方法以及属性都可以直接从Chat对象中直接访问?

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

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

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

你必须要小心的一件事是以一种非常低效地利用Realm的方式抽象逻辑。

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

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