美文网首页1
Swift-Realm数据库的使用详解

Swift-Realm数据库的使用详解

作者: 致青春_bf42 | 来源:发表于2020-03-30 13:36 被阅读0次

    概述

    Realm 是一个跨平台的移动数据库引擎,其性能要优于 Core Data 和 FMDB - 移动端数据库性能比较, 我们可以在 Android 端 realm-java,iOS端:Realm-Cocoa,同时支持 OC 和 Swift两种语言开发。其使用简单,免费,性能优异,跨平台的特点广受程序员GG喜爱。

    Realm 中文文档

    本文将结合一些实战演练讲解 Realm 的用法,干货满满!

    Realm 支持如下属性的存储

    • Int,Int8,Int16,Int32 和 Int64
    • Boolean 、 Bool
    • Double 、 Float
    • String
    • NSDate 、 Date(精度到秒)
    • NSData 、 Data
    • 继承自 Object 的类 => 作为一对一关系(Used for One-to-one relations)
    • List => 作为一对多关系(Used for one-to-many relations)
    Realm 安装 - 使用 CocoaPods

    pod 'RealmSwift'
    pod 'Realm'

    Realm 配置
    • 在 AppDelegate 的 didFinishLaunchingWithOptions 方法中调用以下方法,这个方法主要用于数据模型属性增加或删除时的数据迁移,每次模型属性变化时,将 dbVersion 加 1 即可,Realm 会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构,移除属性的数据将会被删除。
    ///配置数据库
       RealmHelper.configRealm()
    

    configRealm方法说明如下

        ///  配置数据库
        public class func configRealm() {
            /// 这个方法主要用于数据模型属性增加或删除时的数据迁移,每次模型属性变化时,将 dbVersion 加 1 即可,Realm 会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构,移除属性的数据将会被删除。
            let dbVersion : UInt64 = 1
            let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
            let dbPath = docPath.appending("/defaultDB.realm")
            let config = Realm.Configuration(fileURL: URL.init(string: dbPath), inMemoryIdentifier: nil, syncConfiguration: nil, encryptionKey: nil, readOnly: false, schemaVersion: dbVersion, migrationBlock: { (migration, oldSchemaVersion) in
                
            }, deleteRealmIfMigrationNeeded: false, shouldCompactOnLaunch: nil, objectTypes: nil)
            Realm.Configuration.defaultConfiguration = config
            Realm.asyncOpen { (realm, error) in
                if let _ = realm {
                    print("Realm 服务器配置成功!")
                }else if let error = error {
                    print("Realm 数据库配置失败:\(error.localizedDescription)")
                }
            }
        }
    
    

    定义模型

    import UIKit
    import RealmSwift
    import Realm
    
    class Book: Object {
        @objc dynamic var name = ""
        @objc dynamic var author = ""
        
        convenience init(name : String,author : String) {
              self.init();
              self.name = name;
              self.author = author;
          }
        
        /// LinkingObjects 反向表示该对象的拥有者
          let owners = LinkingObjects(fromType: Student.self, property: "books")
        
    }
    
    class Student: Object {
      
        @objc dynamic var name = ""
        @objc dynamic var age = 18
        @objc dynamic var weight = 156
        @objc dynamic var id = 0
        @objc dynamic var address = ""
        @objc dynamic var birthday : NSDate? = nil
        @objc dynamic var photo : NSData?  = nil
        
        //重写 Object.primaryKey() 可以设置模型的主键。
          //声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。
          //一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。
        override static func primaryKey() -> String? {
              return "id"
          }
    
          //重写 Object.ignoredProperties() 可以防止 Realm 存储数据模型的某个属性
          override static func ignoredProperties() -> [String] {
              return ["tempID"]
          }
    
          //重写 Object.indexedProperties() 方法可以为数据模型中需要添加索引的属性建立索引,Realm 支持为字符串、整型、布尔值以及 Date 属性建立索引。
          override static func indexedProperties() -> [String] {
              return ["name"]
          }
          
          //List 用来表示一对多的关系:一个 Student 中拥有多个 Book。
          let books = List<Book>()
    
    }
    
    
    需要注意的是:在使用Realm中存储的数据模型都要是 Object 类的子类。
    1. 设置主键 - primaryKey

    重写 Object.primaryKey() 可以设置模型的主键。
    声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。
    一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。

     override static func primaryKey() -> String? {
            return "id"
        }
    
    1. 忽略属性 - ignoredProperties

    重写 Object.ignoredProperties() 可以防止 Realm 存储数据模型的某个属性。Realm 将不会干涉这些属性的常规操作,它们将由成员变量(var)提供支持,并且您能够轻易重写它们的 setter 和 getter。

        override static func ignoredProperties() -> [String] {
            return ["tempID"]
        }
    

    3)索引属性 - indexedProperties

    重写 Object.indexedProperties() 方法可以为数据模型中需要添加索引的属性建立索引,Realm 支持为字符串、整型、布尔值以及 Date 属性建立索引。

        override static func indexedProperties() -> [String] {
            return ["name"]
        }
    

    4)使用List实现一对多关系 - indexedProperties

    List 用来表示一对多的关系:一个 Student 中拥有多个 Book。
    List 中可以包含简单类型的 Object,表面上和可变的 Array 非常类似,所用的方法和访问数据的方式(索引和下标)都相同,并且所包含的所有对象都应该是相同类型的。声明前面不可加 dynamic ,因为在 Objective-C 运行时无法表示泛型属性。
    注意:List 只能够包含 Object 类型,不能包含诸如String之类的基础类型。

        //List 用来表示一对多的关系:一个 Student 中拥有多个 Book。
        let books = List<Book>()
    

    5)反向关系 - LinkingObjects

    通过反向关系(也被称为反向链接(backlink)),您可以通过一个特定的属性获取和给定对象有关系的所有对象。 Realm 提供了“链接对象 (linking objects)” 属性来表示这些反向关系。借助链接对象属性,您可以通过指定的属性来获取所有链接到指定对象的对象。
    例如:一个 Book 对象可以拥有一个名为 owners 的链接对象属性,这个属性中包含了某些 Student 对象,而这些 Student 对象在其 books 属性中包含了这一个确定的 Book 对象。您可以将 owners 属性设置为 LinkingObjects 类型,然后指定其关系,说明其当中包含了其拥有者 Student 对象。

      let owners = LinkingObjects(fromType: Student.self, property: "books")
    

    1.增

        ///新增单条数据
        public class func addObject<T>(object: T){
            
            do {
                let defaultRealm = self.getDB()
                try defaultRealm.write {
                    defaultRealm.add(object as! Object)
                }
                print(defaultRealm.configuration.fileURL ?? "")
            } catch {}
            
        }
            
        /// 保存多条数据
        public class func addObjects<T>(by objects : [T]) -> Void {
            let defaultRealm = self.getDB()
            try! defaultRealm.write {
                defaultRealm.add(objects as! [Object])
            }
            print(defaultRealm.configuration.fileURL ?? "")
        }
    

    2.删

        /// 删除单条
        /// - Parameter object: 删除数据对象
        public class func deleteObject<T>(object: T?) {
            
            if object == nil {
                print("无此数据")
                return
            }
            
            do {
                  let defaultRealm = self.getDB()
                  try defaultRealm.write {
                      defaultRealm.delete(object as! Object)
                  }
            } catch {}
        }
        
        
        /// 删除多条数据
        /// - Parameter objects: 对象数组
        public class func deleteObjects<T>(objects: [T]?) {
            
            if objects?.count == 0 {
                print("无此数据")
                return
            }
            
            do {
                  let defaultRealm = self.getDB()
                  try defaultRealm.write {
                      defaultRealm.delete(objects as! [Object])
                  }
            } catch {}
        }
    
        
        /// 根据条件去删除单条/多条数据
        public class func deleteObjectFilter<T>(objectClass: T, filter: String?) {
            
            let objects = RealmHelper.queryObject(objectClass: objectClass, filter: filter)
            RealmHelper.deleteObjects(objects: objects)
            
        }
        
       
        /// 删除某张表
        /// - Parameter objectClass: 删除对象
          public class func clearTableClass<T>(objectClass: T) {
              
              do {
                    let defaultRealm = self.getDB()
                    try defaultRealm.write {
                        defaultRealm.delete(defaultRealm.objects((T.self as! Object.Type).self))
                    }
              } catch {}
          }
    

    3.更新

    ///更新单条数据
        public class func updateObject<T>(object: T) {
            
            do {
                let defaultRealm = self.getDB()
                try defaultRealm.write {
                    defaultRealm.add(object as! Object, update: .error)
                }
            }catch{}
        }
        
        
        
        /// 更新多条数据
        public class func updateObjects<T>(objects : [T]) {
            let defaultRealm = self.getDB()
            try! defaultRealm.write {
                defaultRealm.add(objects as! [Object], update: .error)
            }
        }
        
        /// 更新多条数据的某一个属性
        public class func updateObjectsAttribute<T>(objectClass : T ,attribute:[String:Any]) {
            let defaultRealm = self.getDB()
            try! defaultRealm.write {
                let objects = defaultRealm.objects((T.self as! Object.Type).self)
                let keys = attribute.keys
                 for keyString in keys {
                    objects.setValue(attribute[keyString], forKey: keyString)
                }
            }
        }
    

    4.查询

    /// 查询数据
        /// - Parameters:
        ///   - objectClass: 当前查询对象
        ///   - filter: 查询条件
        class func queryObject <T> (objectClass: T, filter: String? = nil) -> [T]{
            
            let defaultRealm = self.getDB()
            var results : Results<Object>
            
            if filter != nil {
                     
                results =  defaultRealm.objects((T.self as! Object.Type).self).filter(filter!)
            }
            else {
                     
                results = defaultRealm.objects((T.self as! Object.Type).self)
            }
            
            guard results.count > 0 else { return [] }
            var objectArray = [T]()
            for model in results{
               objectArray.append(model as! T)
            }
           
            return objectArray
            
        }
    

    注:

    通过 Realm Browser 查看刚才保存的数据

    通过 print(realm.configuration.fileURL ?? "") 打印数据路径

    以下提供Demo地址

    Demo下载地址

    相关文章

      网友评论

        本文标题:Swift-Realm数据库的使用详解

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