Swift-RealmSwift 的使用

Swift版本的Realm测试用例,有关Realm介绍请看之前 OC的文章
目录:
1、Realm库的配置
2、增
3、删
4、改
5、查
6、个人信息的存储和调试

一、Realm库的配置

/**
 Realm 致力于平衡数据库读取的灵活性和性能。为了实现这个目标,在 Realm 中所存储的信息的各个方面都有基本的限制。例如:
 (1)类名称的长度最大只能存储 57 个 UTF8 字符。
 (2)属性名称的长度最大只能支持 63 个 UTF8 字符。
 (3)NSData 以及 String 属性不能保存超过 16 MB 大小的数据。如果要存储大量的数据,可通过将其分解为16MB 大小的块,或者直接存储在文件系统中,然后将文件路径存储在 Realm 中。如果您的应用试图存储一个大于 16MB 的单一属性,系统将在运行时抛出异常。
 (4)对字符串进行排序以及不区分大小写查询只支持“基础拉丁字符集”、“拉丁字符补充集”、“拉丁文扩展字符集 A” 以及”拉丁文扩展字符集 B“(UTF-8 的范围在 0~591 之间)。
 */

// 事件闭包(做完Realm操作后的事件)
public typealias RealmDoneTask = () -> Void
class RealmTools: NSObject {
    /// 单粒
    static let sharedInstance = RealmTools()
    /// 当前的 Realm
    fileprivate var currentRealm: Realm?
    /// 当前realm存储的路径
    static var fileURL: URL? {
        return sharedInstance.currentRealm?.configuration.fileURL
    }
    /// 当前的版本号
    fileprivate var currentSchemaVersion: UInt64 = 0
    /// 当前的加密字符串
    fileprivate var currentKeyWord: String? = ""
}

// MARK:- Realm数据库配置和版本差异化配置
/**
 通过调用 Realm() 来初始化以及访问我们的 realm 变量。其指向的是应用的 Documents 文件夹下的一个名为“default.realm”的文件。
 通过对默认配置进行更改,我们可以使用不同的数据库。比如给每个用户帐号创建一个特有的 Realm 文件,通过切换配置,就可以直接使用默认的 Realm 数据库来直接访问各自数据库
 */
// 在(application:didFinishLaunchingWithOptions:)中进行配置
extension RealmTools {

    // MARK: 配置数据库,为用户提供个性化的 Realm 配置(加密暂时没有使用)
    /// 配置数据库,为用户提供个性化的 Realm 配置
    /// - Parameters:
    ///   - userID: 用户的ID
    ///   - keyWord: 加密字符串
    ///   - schemaVersion: 设置新的架构版本(如果要存储的数据模型属性发生变化),这个版本号必须高于之前所用的版本号,如果您之前从未设置过架构版本,那么这个版本号设置为 0)
    static func configRealm(userID: String?,
                        keyWord: String? = nil,
                        schemaVersion: UInt64 = 0, migrationBlock: MigrationBlock? = nil) {
        // 加密串128位结果为:464e5774625e64306771702463336e316a4074487442325145766477335e21346b715169364c406c6a4976346d695958396245346e356f6a62256d2637566126
        // let key: Data = "FNWtb^d0gqp$c3n1j@tHtB2QEvdw3^!4kqQi6L@ljIv4miYX9bE4n5ojb%m&7Va&".data(using: .utf8, allowLossyConversion: false)!
        // 加密的key
        // let key: Data = keyWord.data(using: .utf8, allowLossyConversion: false)!
        // 打开加密文件
        // (encryptionKey: key)
        // 使用默认的目录,但是使用用户 ID 来替换默认的文件名
        let fileURL = FileManager.DocumnetsDirectory() + "/" + ("\(userID ?? "")default.realm")
        let config = Realm.Configuration(fileURL: URL(string: fileURL), schemaVersion: schemaVersion, migrationBlock: { (migration, oldSchemaVersion) in
            // 目前我们还未进行数据迁移,因此 oldSchemaVersion == 0
            if oldSchemaVersion < 1 {
                // 什么都不要做!Realm 会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构
            }
            // 低版本的数据库迁移......
            if migrationBlock != nil {
                migrationBlock!(migration, oldSchemaVersion)
            }
        })
        // 告诉 Realm 为默认的 Realm 数据库使用这个新的配置对象
        Realm.Configuration.defaultConfiguration = config
        guard let realm = try? Realm(configuration: config) else {
            return
        }
        sharedInstance.currentSchemaVersion = schemaVersion
        sharedInstance.currentRealm = realm
        sharedInstance.currentKeyWord = keyWord
    }

    // MARK: 删除当前的realm库
    /// 删除当前的realm库
    @discardableResult
    static func deleteRealmFiles() -> Bool {
        let realmURL = sharedInstance.currentRealm?.configuration.fileURL ?? Realm.Configuration.defaultConfiguration.fileURL!
        let realmURLs = [
            realmURL,
            realmURL.appendingPathExtension("lock"),
            realmURL.appendingPathExtension("management")
        ]
        for URL in realmURLs {
            do {
                try FileManager.default.removeItem(at: URL)
                self.configRealm(userID: nil, keyWord: sharedInstance.currentKeyWord, schemaVersion: sharedInstance.currentSchemaVersion)
            } catch {
                // handle error
               return false
            }
        }
        return true
    }
}

二、增

// MARK:- 增
extension RealmTools {

    // MARK: 添加单个对象
    /// 添加单个对象
    /// - Parameters:
    ///   - object: 对象
    ///   - update: 是否更新
    ///   - task: 添加后操作
    static func add(_ object: Object, update: Realm.UpdatePolicy = .error, task: @escaping RealmDoneTask) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            weakCurrentRealm.add(object, update: update)
            task()
        }
    }

    // MARK: 添加多个对象
    /// 添加多个对象
    /// - Parameters:
    ///   - objects: 对象组
    ///   - update: 是否更新
    ///   - task: 添加后操作
    static func addList(_ objects: Array<Object>, update: Realm.UpdatePolicy = .error, task: @escaping RealmDoneTask) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            weakCurrentRealm.add(objects, update: update)
            task()
        }
    }
}

三、删

// MARK:- 删
extension RealmTools {

    // MARK: 在事务中删除一个对象
    /// 在事务中删除一个对象
    /// - Parameters:
    ///   - object: 单个被删除的对象
    ///   - task: 删除后操作
    static func delete(_ object: Object, task: @escaping RealmDoneTask) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            weakCurrentRealm.delete(object)
            task()
        }
    }

    // MARK: 在事务中删除多个对象
    /// 在事务中删除多个对象
    /// - Parameters:
    ///   - objects: 多个要被删除的对象
    ///   - task: 删除后操作
    static func deleteList(_ objects: Array<Object>, task: @escaping RealmDoneTask) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            weakCurrentRealm.delete(objects)
            task()
        }
    }

    // MARK: 删除所有数据(不要轻易调用)
    /// 从 Realm 中删除所有数据
    /// - Parameter task: 删除后操作
    static func deleteAll(task: @escaping RealmDoneTask) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            weakCurrentRealm.deleteAll()
            task()
        }
    }

    // MARK: 根据条件删除对象
    /// 根据条件删除对象
    /// - Parameters:
    ///   - object: 对象类型
    ///   - predicate: 条件
    static func deleteByPredicate(object: Object.Type, predicate: NSPredicate) {
        guard let results: Array<Object> = objectsWithPredicate(object: object, predicate: predicate) else {
            return
        }
        deleteList(results) {
        }
    }
}

四、改

// MARK:- 改
extension RealmTools {

    // MARK: 更改某个对象(根据主键存在来更新,元素必须有主键)
    /// 更改某个对象(根据主键存在来更新)
    /// - Parameters:
    ///   - object: 某个对象
    ///   - update: 是否更新
    static func update(object: Object, update: Realm.UpdatePolicy = .modified) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            weakCurrentRealm.add(object, update: update)
        }
    }

    // MARK: 更改多个对象(根据主键存在来更新,元素必须有主键)
    /// 更改多个对象(根据主键存在来更新)
    /// - Parameters:
    ///   - objects: 多个对象
    ///   - update: 是否更新
    static func updateList(objects: Array<Object>, update: Realm.UpdatePolicy = .modified) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            weakCurrentRealm.add(objects, update: .modified)
        }
    }

    // MARK: 更新操作,对于realm搜索结果集当中的元素,在action当中直接赋值即可修改(比如查询到的某些属性可直接修改)
    /// 更新操作,对于realm搜索结果集当中的元素,在action当中直接赋值即可修改
    /// - Parameter action: 操作
    static func updateWithTranstion(action: (Bool) -> Void) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        try? weakCurrentRealm.write {
            action(true)
        }
    }

    // MARK: 更新一个一个对象的多个属性值(根据主键存在来更新,元素必须有主键)
    /// 更新一个一个对象的多个属性值
    /// - Parameters:
    ///   - object: 对象类型
    ///   - value: 数组数组
    ///   - update: 更新类型
    static func updateObjectAttribute(object: Object.Type, value: Any = [:], update: Realm.UpdatePolicy = .modified) {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return
        }
        do {
            try weakCurrentRealm.write {
                weakCurrentRealm.create(object, value: value, update: update)
            }
        } catch _ {
        
        }
    }
}

五、查

// MARK:- 查
extension RealmTools {
    // MARK: 查询某个对象数据
    /// 查询某个对象数据
    /// - Parameter type: 对象类型
    /// - Returns: 返回查询的结果
    static func objects(_ object: Object.Type) -> Array<Object>? {
        guard let results = queryWithType(object: object) else {
            return nil
        }
        return resultsToObjectList(results: results)
    }

    // MARK: 查询某个对象数据(根据条件)
    /// 查询某个对象数据(根据条件)
    /// - Parameters:
    ///   - object: 对象类型
    ///   - predicate: 查询条件
    /// - Returns: 返回查询结果
    static func objectsWithPredicate(object: Object.Type, predicate: NSPredicate) -> Array<Object>? {
        guard let results = queryWith(object: object, predicate: predicate) else {
            return nil
        }
        return resultsToObjectList(results: results)
    }

    // MARK: 带排序条件查询
    ///  带排序条件查询
    /// - Parameters:
    ///   - object: 对象类型
    ///   - predicate:  查询条件
    ///   - sortedKey: 排序的键
    ///   - isAssending: 升序还是降序,默认升序
    /// - Returns: 返回查询对象数组
    static func objectsWithPredicateAndSorted(object: Object.Type,
                                       predicate: NSPredicate,
                                       sortedKey: String,
                                     isAssending: Bool = true) -> Array<Object>? {
        guard let results = queryWithSorted(object: object, predicate: predicate, sortedKey: sortedKey, isAssending: isAssending) else {
            return nil
        }
        return resultsToObjectList(results: results)
    }

    // MARK: 带分页的查询
    /// 带分页的查询
    /// - Parameters:
    ///   - object: 对象类型
    ///   - predicate: 查询条件
    ///   - sortedKey: 排序的键
    ///   - isAssending: 升序还是降序,默认升序
    ///   - fromIndex: 起始页
    ///   - pageSize: 一页的数量
    /// - Returns: 返回查询对象数组
    static func objectsWithPredicateAndSortedForPages(object: Object.Type,
                                                  predicate: NSPredicate,
                                                  sortedKey: String,
                                                  isAssending: Bool,
                                                  fromIndex: Int,
                                                  pageSize: Int) -> Array<Object>? {
        guard let results = queryWithSorted(object: object,
                                     predicate: predicate,
                                     sortedKey: sortedKey,
                                 isAssending: isAssending) else {
            return nil
        }
        var resultsArray = Array<Object>()
        if results.count <= pageSize * (fromIndex - 1) || fromIndex <= 0 {
            return resultsArray
        }
        if results.count > 0 {
            for i in pageSize * (fromIndex - 1)...(fromIndex * pageSize - 1) {
                resultsArray.append(results[I])
            }
        }
        return resultsArray
    }
}

//MARK:- 私有(查询)
extension RealmTools {

    /// 查询某个对象数据
    /// - Parameter object: 对象类型
    /// - Returns: 返回查询对象数组
    private static func queryWithType(object: Object.Type) -> Results<Object>? {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return nil
        }
        return weakCurrentRealm.objects(object)
    }

    // MARK: 根据条件查询数据
    /// 根据条件查询数据
    /// - Parameters:
    ///   - object: 对象类型
    ///   - predicate: 查询条件
    /// - Returns: 返回查询对象数组
    private static func queryWith(object: Object.Type,
                           predicate: NSPredicate) -> Results<Object>? {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return nil
        }
        return weakCurrentRealm.objects(object).filter(predicate)
    }

    // MARK: 带排序条件查询
    /// 带排序条件查询
    /// - Parameters:
    ///   - object: 对象类型
    ///   - predicate: 查询条件
    ///   - sortedKey: 排序的键
    ///   - isAssending: 升序还是降序,默认升序
    /// - Returns: 返回查询对象数组
    private static func queryWithSorted(object: Object.Type,
                                 predicate: NSPredicate,
                                 sortedKey: String,
                               isAssending: Bool = true) -> Results<Object>? {
        guard let weakCurrentRealm = sharedInstance.currentRealm else {
            return nil
        }
        return weakCurrentRealm.objects(object).filter(predicate)
        .sorted(byKeyPath: sortedKey, ascending: isAssending)
    }

    // MARK: 查询结果转Array<Object>
    /// 查询结果转Array<Object>
    /// - Parameter results: 查询结果
    /// - Returns: 返回Array<Object>
    private static func resultsToObjectList(results: Results<Object>) -> Array<Object> {
        var resultsArray = Array<Object>()
        if results.count > 0 {
            for i in 0...(results.count - 1) {
                resultsArray.append(results[I])
            }
        }
        return resultsArray
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,706评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,002评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,462评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,375评论 0 216
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,763评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,849评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,033评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,768评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,490评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,734评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,204评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,566评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,227评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,137评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,934评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,926评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,774评论 2 274

推荐阅读更多精彩内容