美文网首页移动客户端iOS开发
iOS开发-RealmSwift的使用及数据迁移

iOS开发-RealmSwift的使用及数据迁移

作者: ForgetSou | 来源:发表于2020-12-04 14:58 被阅读0次

    一. 简述

    Realm 是一个跨平台的移动数据库引擎。

    Realm 中文文档

    Realm平台是基于noSQL的服务器和客户端组件的组合,该组件通过快速高效的同步协议进行连接,以实现实时,连接的应用程序和服务,无论网络状态如何,它们都具有响应能力和性能。Realm平台具有两个主要组件:Realm数据库和Realm对象服务器。这两个组件协同工作以自动同步数据,从而实现大量用例,从离线优先应用程序,现场服务和数据收集应用程序,以数据可用性和用户响应能力为关键的移动服务开始。此外,通过与现有后端(SQL,Kafka等)的集成功能,Realm Platform是一种在利用现有(有时是传统)系统和数据源的同时构建现代实时服务体验的绝佳方法。

    领域平台的高级示意图

    Realm数据库嵌入在客户端上,是一个功能齐全的,面向对象的跨平台数据库,可将数据本地存储在设备上。它适用于主要的移动语言,例如Swift和Objective-C(iOS),Java(Android),C#(Xamarin,.NET)和JavaScript(React Native和Node.js)。

    Realm数据库是轻量级且高性能的,能够处理非常大的数据负载并在几分之一秒内运行查询。它基于共享的活动对象,无需编写网络,序列化或对象关系映射代码,即可与Realm Object Server实时无缝同步数据。

    Realm 性能优于 FMDB 和 Core Data,支持 OC 和 Swift 语言开发,使用更加简单、方便。

    下面主要说下Swift语言下的 Realm 数据库的使用和 RealmSwift 数据迁移

    二. Cocopods 安装

    pod 'RealmSwift'
    

    三. 数据模型

    不再详述了,具体可参考中文官方文档-数据模型

    Realm 支持的属性

    类型 非可空值形式 可空值形式
    Bool @objc dynamic var value = false let value = RealmOptional<Bool>()
    Int @objc dynamic var value = 0 let value = RealmOptional<Int>()
    Float @objc dynamic var value: Float = 0.0 let value = RealmOptional<Float>()
    Double @objc dynamic var value: Double = 0.0 let value = RealmOptional<Double>()
    String @objc dynamic var value = "" @objc dynamic var value: String? = nil
    Data @objc dynamic var value = Data() @objc dynamic var value: Data? = nil
    Date @objc dynamic var value = Date() @objc dynamic var value: Date? = nil
    Object 不存在:必须是可空值 @objc dynamic var value: Class?
    List let value = List<Type>() 不存在:必须是非可空值
    LinkingObjects let value = LinkingObjects(fromType: Class.self, property: "property") 不存在:必须是非可空值

    四. 数据迁移

    当您使用任意一个数据库时,您随时都可能打算修改您的数据模型。由于 Realm 的数据模型是以标准的 Swift 类来定义的,这使得修改模型就像修改其他的 Swift 类一样方便。

    例如在1.0.1版本定义的 Person,现在需要在1.0.2版本中添加一个 email 的属性。

    // 1.0.1版本定义的Person
    class Person: Object {
        @objc dynamic var name = ""
        @objc dynamic var age = 0
    }
    // 1.0.2版本新增email属性
    class Person: Object {
        @objc dynamic var name = ""
        @objc dynamic var age = 0
        @objc dynamic var email = ""
    }
    

    如下是具体处理这类问题的实现方式

    // Swift 数据库管理器中的init()方法中做数据迁移
    override init() {
            let realmName = "demo.realm"
            
            let defaultUrl = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first
            let configCompact = Realm.Configuration(
                fileURL: defaultUrl?.appendingPathComponent("\(realmName)"),
                shouldCompactOnLaunch: { totalBytes, usedBytes in
                let oneHundredMB = 100 * 1024 * 1024
                return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
            })
            
            do {
                // 如果满足配置块条件,则在第一次打开时压缩 Realm
                _ = try Realm(configuration: configCompact)
            } catch {
                // 处理压缩或打开 Realm 的错误
            }
    
            let currentVersion : String = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
            let currentVersions = currentVersion.components(separatedBy: ".")
            let currentVersionStr = NSMutableString()
            for subVersion in currentVersions {
                let subs = String(format: "%02d", (subVersion as NSString).integerValue)
                currentVersionStr.append(subs)
            }
              /*!
             * 当前版本的UInt64版本号
             * 如currentVersion = "1.0.1",schemaVersion = 010001; currentVersion = 10.12.25, schemaVersion = 101225
             * !!! 注意 !!!
             * 在打包定义版本的时候,版本规则:
             * 1.版本号只能是三位,如1.12.18,中间只能两个小数点;相反1.12.18.2或者1.22等禁用的。
             * 2.版本号不能超过100,如定义到1.0.99或者1.99.1时,之后的下个版本不能定义1.0.100或1.100.0
             */
            let schemaVersion : UInt64 = UInt64(currentVersionStr as String)!
            let config = Realm.Configuration(
                fileURL: defaultUrl?.appendingPathComponent("\(realmName)"),
                schemaVersion: schemaVersion,
                migrationBlock: { migration, oldSchemaVersion in
                    if (oldSchemaVersion < schemaVersion) {
                        migration.enumerateObjects(ofType: Person.className()) { (oldObject, newObject) in
                                                     // 新增字段
                             newObject!["email"] = ""
                        }
                        migration.enumerateObjects(ofType: Student.className()) { (oldObject, newObject) in
                                                     // 改字段
                             let firstName = oldObject!["firstName"] as! String
                             let lastName = oldObject!["lastName"] as! String
                             newObject!["fullName"] = "\(firstName) \(lastName)"
                        }
                    }
            })
    
            Realm.Configuration.defaultConfiguration = config
            _ = try! Realm()
        }
    

    🏡 个人博客 ForgetSou


    相关文章

      网友评论

        本文标题:iOS开发-RealmSwift的使用及数据迁移

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