美文网首页swift
Swift 数据库 RealmSwift + ObjectMap

Swift 数据库 RealmSwift + ObjectMap

作者: YourSummer | 来源:发表于2022-08-02 11:30 被阅读0次

    RealmSwift使用注意事项:

    只要更改了模型的任意一个属性, 数据库版本号就必须增加, 不然就会崩溃,开发时稍微留心, 如果是上线那么有一种解决方案
    • 因为上线必定会升级版本号, 所以App版本号可以作为数据库版本号
    • 比如本次上线版本号是 1.2.0
    • 那么我们需要把 1.2.0处理成 102000, 然后作为数据库的版本号
    1. 将1.2.0去掉'.', 成为一个字符串"120"
    2. 再给字符串的每一个字符后边添加一个"0"
    3. 转换成UIInt64类型, 作为数据库的版本号
    • 当然如果你们的App版本号是类似这种: 1.2.345, 那么就需要给字符串长度不超过3位的后边添加两个"0", 变成: 100200345, 这个逻辑代码中会提供, 可以参考
    1. 创建数据库
    import RealmSwift
    
    open class RealmManager: NSObject {
        public var realm: Realm!
        
        public override init() {
            do {
                realm = try Realm(name: "your_realm_name")
            } catch {
                print("open realm error = \(error.localizedDescription)")
            }
        }
        
        // 更新数据库版本
        // 只要数据模型有变动就必须升级数据库版本
        // 每次上线版本都会默认用最新的版本号作为数据库版本号, 例如: 1.2.0 对应数据库版本号: 102000
        static public func update(realmVersion: UInt64) {
            let config = Realm.Configuration(
                schemaVersion: realmVersion,
                migrationBlock: { migration, oldSchemaVersion in }
            )
            
            Realm.Configuration.defaultConfiguration = config
        }
    }
    
    extension Realm {
    
        public init(name: String) throws {
            // 找到沙盒路径 这里是Document
            let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,
                                                              .userDomainMask,
                                                              true).first!
            // 拼接自己的路径
            let dbPath = docPath + "/db/" + name
            // 创建文件夹
            if !FileManager.default.fileExists(atPath: dbPath) {
                try FileManager.default.createDirectory(atPath: dbPath,
                                                    withIntermediateDirectories: true,
                                                    attributes: nil)
            }
            // 根据路径创建自己的realm文件URL
            let url = URL(string: dbPath + "/" + name + ".realm")
            try self.init(fileURL: url!)
        }
    }
    
    1. 封装单个模型的数据存储管理类
    import Foundation
    import RealmSwift
    
    // 单个对象的存储
    open class SingleObjectRealm<T: Object>: RealmManager {
        
        // 存储
        open func save(_ t: T) {
            delete()
            try? realm.write({ realm.add(t) })
        }
        
        // 获取
        open func value() -> T? {
            return realm.objects(T.self).first
        }
        
        // 删除
        open func delete() {
            try? realm.write({
                realm.delete(realm.objects(T.self))
            })
        }
        
        // 更新
        open func update(_ callback: (T) -> ()) {
            guard let t = value() else { return }
            try? realm.write{ callback(t)  }
        }
    }
    
    1. 写模型
      这里使用的是ObjectMapper 用于用户信息接口解析成模型
    import Realm
    import RealmSwift
    import Foundation
    import ObjectMapper
    
    public class User: Object, Mappable {
    
        @Persisted public var name = ""
        @Persisted public var userId = 0
        @Persisted public var account = ""
        @Persisted public var headUrl = ""
        @Persisted public var birthday = ""
        
        required override init() { }
        
        required public init?(map: ObjectMapper.Map) { }
    
        public func mapping(map: ObjectMapper.Map) {
            name <- map["name"]
            userId <- map["userid"]
            account <- map["account"]
            headUrl <- map["head_url"]
            birthday <- map["birthday"]
        }
    }
    
    1. 对应User模型的存储处理类
    import Foundation
    
    public class UserManager: SingleObjectRealm<User> {
        public static let shared = UserManager()
        
        public var user: User?
        
        public var isLogin = false
        
        fileprivate override init() {
            super.init()
            user = value()
            isLogin = user != nil
        }
        
        public override func save(_ t: User) {
            super.save(t)
            user = t
            isLogin = true
        }
        
        public override func delete() {
            super.delete()
            user = nil
            isLogin = false
        }
        
        public override func value() -> User? {
            return super.value()
        }
    }
    

    使用:

    • 首先在程序的入口处理数据库版本号
      这个例子是类似于版本号是 1.2.0这种的
    let info = Bundle.main.infoDictionary
    if let versionStr = info?["CFBundleShortVersionString"] as? String {
        let vs = versionStr
            .split(separator: ".")
            .map { (version) -> Substring in
                var v = version
                if v.count == 1 { v.append("0") }
                return v
            }
            .joined()
        if let versionInt = UInt64(vs) {
            print("RealmVersion = \(versionInt)")
            RealmManager.update(realmVersion: versionInt)
        }
    }
    
    • 一般用户信息是在接口返回之后存储, 或者更新
    // 模拟服务端返回的用户数据
    let userJson: [String: Any] = [
        "name": "空格格",
        "userid": "12345",
        "account": "18790737838",
        "birthday": "2022/7/17",
        "head_url": "https: www.xxx.com/user/head"]
    
    // 转换成对象
    if let user = Mapper<User>().map(JSON: userJson) {
        // 存储到数据库
        UserManager.shared.save(user)
    }
    print(NSHomeDirectory())
    
    • token失效等原因退出登录-删除User
    UserManager.shared.delete()
    
    • 更新User中的某个字段值
    UserManager.shared.update { (user) in
            user.name = "张三"
    }
    

    请点击代码详情: 示例demo

    相关文章

      网友评论

        本文标题:Swift 数据库 RealmSwift + ObjectMap

        本文链接:https://www.haomeiwen.com/subject/fghlwrtx.html