前言
iOS数据持久化数据库方式解决方案, 主流的有FMDB(SQLite), CoreData, Realm.
三者中CoreData的使用比较不方便, FMDM需要关注线程安全的问题. 而Realm除了API友好, 在线程处理上也相对方便, 而且可以使用桌面应用Realm Browser查看iOS模拟器的数据库文件.
需要持久化的数据
- 
    
启动广告数据
 - 
    
首页广告数据
 - 
    
登录过的用户的数据
 - 
    
用户的操作记录(搜索记录, 聊天记录, 购物车数据, 编辑页面缓存等)
 - 
    
列表数据缓存
 
持久化策略
首先, 以上数据有一部分是和登录用户无关的, 而不同用户对应的数据应该分开存储. 所以在项目中的库会有N+1个(N是登录用户的个数).
跟登录用户无关的数据包括:
- 
    
启动广告
 - 
    
首页广告
 - 
    
用户获取验证码的记录(用于倒计时)
 - 
    
部分列表数据(视项目而定)
 
然后有少部分数据通过UserDefault保存, 包括:
- 
    
当前登录的用户标识(ID)
 - 
    
是否需要显示广告
 - 
    
需要显示的广告标识(ID)
 
在Thinker.vc项目中会在一个DatabaseService模块里面管理数据库:
1
2
3
4
5
6
7
8
9
10
11
class DatabaseService {
    /// 单例
    static let shared: DatabaseService
    
    /// 基本数据库
    public let defaultDatabase: Realm
    
    /// 用户相关数据库
    public var userDatabase: Realm?
}
其中defaultDatabase是固定的, 而userDatabase是根据登录用户切换的. 
根据Realm的文档, 我们可以通过Realm.Configuration来配置数据库所在路径. 
根据场景, defaultDatabase使用默认路径即可.
而userDatabase则根据用户的id来配置. 
这个需要通过绑定用户的登出与登入行为来切换.在Thinker.vc的项目中, 通过RxSwift来绑定UserService中对应的Observable. 先不讨论.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class DatabaseService {
    /// 单例
    static let shared: DatabaseService = DatabaseService()
    
    /// 基本数据库
    public let defaultDatabase: Realm = {
        var config = Realm.Configuration.defaultConfiguration
        // buildVersion是app对应的build版本, 只增不减. 目的是为了数据库migration*
        config.schemaVersion = UInt64(buildVersion as! String)!
        return try! Realm(configuration: config)
    }()
    
    /// 用户相关数据库
    public var userDatabase: Realm? = nil
    
    private init() {
        ...
        ...
    }
    
    /// 根据用户切换数据库
    func updateUserDatabase(for user: UserModel?) {
        guard let uid = user?.uid else {return}
        
        // https://realm.io/docs/swift/latest/#configuring-a-realm  根据uid命名数据库
        let fileUrl = Realm.Configuration.defaultConfiguration.fileURL!.deletingLastPathComponent().appendingPathComponent("user_\(uid).realm")
        let config = Realm.Configuration(fileURL: fileUrl, schemaVersion: UInt64(buildVersion as! String)!)
        
        self.userDatabase = try! Realm(configuration: config)
    }
}
CogfigService模块管理配置数据, 其中就包括了UserDefault要保存的数据: 
(泛型配合UserDefault便捷加载数据)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// UserDefault关键字管理
private struct UserDefaultKeys {
    
    /// 首页广告id
    static let indexAdvertisementID: String = "UserDefaultKeys.indexAdvertisementID"
    
    /// 首页是否显示过
    static let indexAdvertisementShown: String = "UserDefaultKeys.indexAdvertisementShown"
    
    /// 是否显示过引导页
    static let guideShown: String = "UserDefaultKeys.guideShown"
    
    /// 登录用户id
    static let userID: String = "UserDefaultKeys.userID"
}
Realm的Data Model
需要继承Realm的基本类Object, 使用非常方便.
To be continued...