美文网首页
Swift数据持久化之RealmSwift

Swift数据持久化之RealmSwift

作者: T92 | 来源:发表于2019-02-22 23:55 被阅读43次

在之前的swift 数据持久化之CoreData一文中,曾提到过Realm,说会出一篇使用教程,前段时间断断续续一直在Python的道路上探索,时隔5个月,打算在今天把落下的Realm补上。

Realm简介

  • 一个跨平台的移动终端数据库,基于自己的持久化引擎
  • 比 SQLite 和 Core Data 更好更快更易用,可搭配自家RealmBrowser查看数据
  • 完全免费

GitHub地址
官网地址

注:在Objective-C中是使用Realm,在Swift中名字有了变化,叫做RealmSwift

1.集成到项目

在集成的时候可以手动集成,也可以用cocoapods集成,因为SDK比较大,用cocoapods集成比较慢,如果嫌速度慢,可以去官网下载最新的SDK版本,然后选择对应的swift语言版本(不同版本对应SDK也不相同)手动添加到项目中,手动集成的时候需要注意,如果出现如下错误:

则需要设置工程,在General->Embedded Binaries中导入如下framework

cocoapods集成时在终端输入pod search RealmSwift可以查看相关信息

指定对应版本(如果项目多人合作,建议所有pod项目指定版本号)然后在podfile中添加即可。

2.用法

RealmSwift支持以下的属性类型:Bool、Int8、Int16、Int32、Int64、Double、Float、String、Date、Data,支持一对一,一对多模型存储。

2.1 数据库配置

数据库加密和存储位置,可以根据需求进行操作。但是由于开发过程中涉及到数据迁移,所以必须做迁移相关配置,否则,在模型进行更改之后,数据无法进行迁移从而导致崩溃。

下面做一个最简单的数据迁移配置
AppDelegate.swiftimport RealmSwift,然后在application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool中添加如下代码:

let config = Realm.Configuration(
     schemaVersion: 0,
     migrationBlock: { migration, oldSchemaVersion in
             if (oldSchemaVersion < 0) {}
     })
Realm.Configuration.defaultConfiguration = config

当数据模型属性改变,需要迁移数据时,只需要将schemaVersion: 0oldSchemaVersion < 0中的数字+1即可。当然设置更大也行,但是不允许比之前的版本号小。

2.2 数据模型设计

这里举一个一对多模型例子,其他的举一反三
设计一个Person模型,import RealmSwift,继承自Object,让其具有nameid属性,并将id设置为主键(主键的唯一性由开发者保证)

再设计一个Dog模型,继承自Object,让其具有name属性,一个Person可以拥有多个Dog(用List实现模型一对多)
代码如下:

import UIKit
import RealmSwift

class Person: Object {

    @objc dynamic var name = ""
    var dogs = List<Dog>()
    @objc dynamic var id = 0
    
    //设置主键
    override class func primaryKey() -> String? {
        return "id"
    }
}

class Dog: Object {
    @objc dynamic var name = ""
}

2.3 增

为了方便代码维护,这里新建一个专门管理realm数据库的单例TBRealmManager,其中static let realm = try! Realm()是拿到默认数据库

import UIKit
import RealmSwift

class TBRealmManager: NSObject {
    static let realm = try! Realm()
}

RealmSwift存储、查询、修改以及删除数据时都需要指定数据模型,但是程序员都是懒惰的,代码能少写一行是一行,为了不给每一类模型都单独写增删改查方法,下面方法指定类型全部设计为泛型,这样,不管你要处理什么数据,直接传其类型即可。

向数据库添加数据方法

    class func addModel <T> (model: T){
        do {
            try realm.write {
                realm.add(model as! Object)
            }
        } catch {}
    }

测试

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let dog1 = Dog()
        dog1.name = "大黄"

        let dog2 = Dog()
        dog2.name = "小黑"

        let person = Person()
        person.id = 1
        person.name = "小明"
        person.dogs.append(dog1)
        person.dogs.append(dog2)

        TBRealmManager.addModel(model: person)
    }

}

如果项目跑起来没报错,那么person就已经成功存储到数据库中了,接下来查询一下这个数据

2.4 查

同样的,查询也采用泛型,并增加可选参数filter,当需要指定查询条件时,可以将对应SQL语句给其赋值查询

    class func queryModel <T> (model: T, filter: String? = nil) -> [T]{
        
        var results : Results<Object>
        
        if filter != nil {
            
            results =  realm.objects((T.self as! Object.Type).self).filter(filter!)
        }
        else {
            
            results = realm.objects((T.self as! Object.Type).self)
        }
        
        guard results.count > 0 else { return [] }
        var modelArray = [T]()
        for model in results{
            modelArray.append(model as! T)
        }
        
        return modelArray
    }

测试
为了测试按条件查询,查询前再插入一个Person对象。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let dog1 = Dog()
        dog1.name = "赛虎"

        let dog2 = Dog()
        dog2.name = "豆豆"

        let person = Person()
        person.id = 2
        person.name = "小王"
        person.dogs.append(dog1)
        person.dogs.append(dog2)

        TBRealmManager.addModel(model: person)
        
        let result = TBRealmManager.queryModel(model: Person())
        print("result: ", result)
        
        let result2 = TBRealmManager.queryModel(model: Person(), filter: "name = '小王'")
        print("result2: ", result2)
    }

}

控制台输出结果:


2.5 改

现在将小明的狗“小黑”改名为“小白”

import UIKit
import RealmSwift

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let result = TBRealmManager.queryModel(model: Person(), filter: "name = '小明'")
        print("修改前: ", result)
        
        let model = result.first
        let realm = try! Realm()
        do {
            try realm.write {
                model?.dogs.last?.name = "小白"
            }
        } catch {}
        
        let result2 = TBRealmManager.queryModel(model: Person())
        print("修改后结果: ", result2)
    }

}

控制台输出结果:


当然也可以单独封装一个改的方法,但是在调用时需要重新创建一个主键一致的模型进行更新,如下:

///调用此方法的模型必须具有主键
    class func updateModel <T> (model: T){
        do {
            try realm.write {
                realm.add(model as! Object, update: true)
            }
        }catch{}
    }

测试,更改小明的名字为明明

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let result = TBRealmManager.queryModel(model: Person(), filter: "name = '小明'")
        print("修改前: ", result)
        
        let model = result.first!
        
        let updateModel = Person()
        updateModel.name = "明明"
        updateModel.id = model.id
        updateModel.dogs = model.dogs
        TBRealmManager.updateModel(model: updateModel)
        
        
        let result2 = TBRealmManager.queryModel(model: Person())
        print("修改后结果: ", result2)
    }

}

结果:


2.6 删

    class func deleteModel <T> (model: T){
        do {
            try realm.write {
                realm.delete(model as! Object)
            }
        } catch {}
    }

测试
删除明明这个数据

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let result = TBRealmManager.queryModel(model: Person(), filter: "name = '明明'")
        let model = result.first!
        
        TBRealmManager.deleteModel(model: model)
        
        let result2 = TBRealmManager.queryModel(model: Person())
        print("删除后: ", result2)
    }

}

结果:


当然,也可以直接删除整张表,实质是查询所有结果并进行删除

    ///删除某张表
    class func deleteModelList <T> (model: T){
        
        do {
            try realm.write {
                realm.delete(realm.objects((T.self as! Object.Type).self))
            }
        }catch {}
    }

测试:


可以看到,在删除整张表之后,查询到的结果是一个空数组,说明并无查询结果。

好了,时间有点仓促,明天又是一个加班的日子,各位晚安吧

附 TBRealmManager.swift

import UIKit
import RealmSwift

class TBRealmManager: NSObject {
    
    static let realm = try! Realm()
    
    class func addModel <T> (model: T){
        do {
            try realm.write {
                realm.add(model as! Object)
            }
        } catch {}
    }
    
    class func queryModel <T> (model: T, filter: String? = nil) -> [T]{
        
        var results : Results<Object>
        
        if filter != nil {
            
            results =  realm.objects((T.self as! Object.Type).self).filter(filter!)
        }
        else {
            
            results = realm.objects((T.self as! Object.Type).self)
        }
        
        guard results.count > 0 else { return [] }
        var modelArray = [T]()
        for model in results{
            modelArray.append(model as! T)
        }
        
        return modelArray
    }
    
    class func deleteModel <T> (model: T){
        do {
            try realm.write {
                realm.delete(model as! Object)
            }
        } catch {}
    }
    
    ///删除某张表
    class func deleteModelList <T> (model: T){
        
        do {
            try realm.write {
                realm.delete(realm.objects((T.self as! Object.Type).self))
            }
        }catch {}
    }
    
    ///调用此方法的模型必须具有主键
    class func updateModel <T> (model: T){
        do {
            try realm.write {
                realm.add(model as! Object, update: true)
            }
        }catch{}
    }
    
}

相关文章

网友评论

      本文标题:Swift数据持久化之RealmSwift

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