在MVVM为基础的并发框架中接入Realm

Realm是为移动端打造的数据库,面向对象的数据库,重写了存储引擎,告别ROM,纯粹原生的对象存储。介绍:https://realm.io/cn/news/realm-object-centric-present-day-database-mobile-applications/ 划下重点:1. 数据层库和 ORMs 2. Realm 不是重复现在的技术。

Realm 移动数据库的一个标志性特性:你可以在主线程里面读写!你不用担心这会阻塞你的 UI。但我原来的结构是并发的,数据的增删改查都是异步的,怎么接入?
我接给你看,这就是我要讲的,看上去很脑残,哈哈。

首先我的架构是怎样的,简单描述下:

正如一千个人眼中就有一千个哈姆雷特,所讲的也是我眼中的MVVM

Model
先是 RawModel, 这是Server传输给我的JSON数据的映射产生的Model,最纯粹,最原始的数据,没有任何加工,但我不会在数据库中去存储这个Model。

ViewModel
它是和View的显示直接相关联的,view是容器,我们初始化容器以后,容器怎么呈现给用户,完全依赖于注入的ViewModel。典型的比如UITableView的cell,只通过一个方法bindData方法绑定ViewModel完成渲染。ViewModel中包含一个RawModel的property,所以他们之间的关系是组合关系,当然也可以是继承,方便省去访问RawModel的属性的路由代码,比如viewmodel.model.property需要简写成viewmodel.property,那么需要ViewModel内部写一个属性映射,类似于Rails中的路由操作,组合还是继承看具体模块情况而定,没有定式。ViewModel还包含,用户前端操作需要持久化的一些属性,比如cell中的button按下以后,状态改变,在重启app以后改变还是有效的,那么这个改变需要持久化,所以我选择在db中存储的是ViewModel,
包含Server的数据和Client用户的定制数据,在Sqlite3中以ViewModel为基础做table,或者在OO的数据库中,以ViewModel为基础建立持久化对象。然后VC之间切换,修改ViewModel中的属性,传统方法是KVO,view响应式更新,Swift没有现成的KVO,需要Object继承NSObject,所以建议走系统API,获取那个cell,并重新绑定数据

Manager
MainManager是个Singleton,其中包含类似于UITableView中的数据源,比如一个Array。MainManager会完成数据和view绑定之前最后内存中的操作,比如filter,按照条件过滤数据,还有各种action以后会回掉给其他VC的block,影响下一次数据请求的临时变量,以后Model要是有改动也必须是调用Manager中的方法,记住是数据展现前的最后内存中的操作。对了,还有进入或者退出某个模块的数据初始化操作。MainManager有一个property是DataManager,他负责所有的数据存取,以及通过不同渠道拿到数据以后的merge,会有这些properties:DBRoot,NetworkService,FileManager,DispatchQueue,包含的意义是数据的来源,disk上的db或者file system,还是network,有自己的GCD管理的并发队列,只要在IDE的断点看到这个队列,那么就是在这个DataManager的操作。其实对于上层MainManager来说,他只是请求数据,并不关心来源,需要制定来源可以在methd中增加参数,比如第一次进入VC的时候数据请求的顺序是db,select -> present data -> network request -> present data -> db insert,但是如果是当前VC的refresh操作就不需要请求数据库对吧,这是不一样的

ViewController
每次进入VC会做这么几件事情,basicUI,requestBasicData,bindActions, registNotifications,遇到业务复杂的核心VC,actions会特别多,建议分离到business业务层, 所以又多一个操作叫bindBusiness,记得给一个weak reference 解决retain cycle的问题

说了这么多,看图吧:


DBRoot,
Realm 对象只能通过从最初创建的他的那个线程访问,增删改查的所有操作都必须在这个线程上,因为本来设计是在主线程上,而我的框架是并发的😓。那么,该怎么办?涉及到一个小知识,就是runloop,子线程存活,一个while true 的循环,等待响应,虽然在DataManager的并发的队列上,但是realm的线程只有一个,直到退出模块,销毁所有内容。然后那个NSCondition对象会保证,添加到task pool中的block顺序进行不会有脏数据产生。还有要注意的一点是,realm对象得到的collection是引用是lazy init,所以对collection的直接操作必须还是在realm线程上的,尽管可能已经抛出result到DataManager这一层,注意当前代码所在的队列和线程,好在如果操作不在realm线程上,assert一个断言立刻crash,及时修复错误。
道理都懂,看DBRoot.swift的代码吧:
https://gist.github.com/anonymous/0e5e60bffc677044ab84a1994be0e90d



《在MVVM为基础的并发框架中接入Realm》上有2条评论

  1. We absolutely love your blog and find many of your post’s to be just what I’m looking for. Would you offer guest writers to write content for you? I woudnl’t mind creating a post or elaborating on a lot of the subjects you write regarding here. Again, awesome site!

发表评论

电子邮件地址不会被公开。 必填项已用*标注