Realm 数据库使用

Table of Contents(目录)

0. 项目描述

1. Realm模型

2. Realm数据库安装

3. 创建Model

4. 实现CreateRandomDatabase函数创建初始数据库

创建数据库、删除数据库

创建Model实例,修改Model实例,删除Model实例,增、删、改操作

查询Model,查询、排序、分页操作

5. 数据库结构更新,迁移

6. 数据绑定,数据更新通知,观察者模式


0. 项目描述

Realm练习:约车软件,提供4个页面

  • Tab 1:列出所有当前可约行程
  • Tab 2:列出所有当前用户参与的行程
  • Tab 3:列出所有当前用户参与的留言
  • Tab 4:系统设置页面

本文中只给出了Realm的用法

User Model
userName主键:用户名

mobilePhoneNumber

手机号

portraitImage

头像

qrcodeImage

收款二维码

following

外键 User:关注者列表

fans

外键 User:粉丝列表

cars

外键 Car:用户拥有的车辆列表

apps

外键 Appointment:用户发布的所有行程

enrollapps

外键 Appointment:用户参与的所有行程

sendmessages

外键 Message:用户发送的所有信息

receivemessages

外键 Message:用户接受的所有消息

 

Car Model

brand

车辆品牌
color车辆颜色
id车牌号
owner外键 User:车辆拥有者

 

Appointment Model

createDate

行程创建时间

beginDate

行程开始时间

startLocal

行程开始地点

endLocal

行程结束地点

mobilePhoneNumber

行程发布者手机号

customerNumber

行程可预约人数

costPerCustomer

行程每人单价

car

外键 Car:行程所使用的的汽车

customer

外键 User:行程中的所有乘客

owner

外键 User:行程发布者

 

Message Model

msg

信息内容
createDate信息创建时间
sender外键 User:信息发送人
receiver外键 User:信息接收人


1. Realm模型

  • Realm为关系型数据库,每一个表使用一个Model类表示,每一个列对应Model类中的
  • 每一个线程可以拥有一个Realm数据链接,使用class Realm类创建一个链接,该类可以实现数据链接,执行查询,更新数据表结构,数据迁移,数据绑定等操作
  • 每一个Model类都继承自Realm库中的class Object类,继承后便可进行数据表的增删改查操作
  • 数据表之间的关系由Model类中的属性给出,使用class List<T>以及class LinkingObjects表示外键 
  • 可以通过重载Model类中的函数来定义数据表的一些属性,如func primaryKey函数可以定义表格的主键

官方 Realm Swift 文档(英文) ,旧版本有中文版

 

2. Realm数据库安装

  • 安装CocoaPods
  • Podfile中添加use_frameworks! 和 pod 'RealmSwift'
  • 终端中执行pod install
  • 使用.xcworkspace文件启动工程

3. 创建Model

//表User
class User: Object {
    //属性列
    @objc dynamic var userName = "庞兴庆"
    @objc dynamic var mobilePhoneNumber = "18612345678"
    @objc dynamic var portraitImage = Data()
    @objc dynamic var qrcodeImage: Data? = nil
    
    //外键
    let following = List<User>()
    let fans = LinkingObjects(fromType: User.self, property: "following")
    
    let cars = List<Car>()
    let apps = List<Appointment>()
    let enrollapps = List<Appointment>()
    
    let sendmessages = List<Message>()
    let receivemessages = List<Message>()
    
    //创建主键
    override class func primaryKey() -> String? {
        return "userName"
    }
}
  • 创建数据表User对应的Model:只要这个类继承自Realm中的Object类即可
  • 创建数据表User中的属性列:使用@objc dynamic var PropertyName = defaultValue形式进行创建,对于必填的列(Non-optional)以及非必填列(Optional)的属性定义方式由下表给出。Object,List,LinkingObjects都可以用于外键对应的列
TypeNon-optionalOptional
Bool@objc dynamic var value = falselet value = RealmOptional<Bool>()
Int@objc dynamic var value = 0let value = RealmOptional<Int>()
Float@objc dynamic var value: Float = 0.0let value = RealmOptional<Float>()
Double@objc dynamic var value: Double = 0.0let 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
Objectn/a: must be optional@objc dynamic var value: Class?
Listlet value = List<Type>()n/a: must be non-optional
LinkingObjectslet value = LinkingObjects(fromType: Class.self, property: "property")n/a: must be non-optional
  • 创建数据表User中的外键:Realm支持一对一、一对多、多对多、以及反向外键,Object与List用于前两种情况
  • 创建鼠标表User中的反向外键:LinkingObjects用于定义反向外键,如Car类中的owner类就可以反向查找到拥有者,不需要额外执行查询操作
  • 创建数据表User中的主键:重载primaryKey可以定义表格的主键,重载indexedProperties可以定义自增加列,重载ignoredProperties可以定义Model中需要忽略的属性

用同样的方式定义Car类,Appointment类,Message类

4. 实现CreateRandomDatabase函数创建初始数据库

  • 创建数据库、删除数据库

//删除数据库
let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
print(realmURL)
let realmURLs = [
    realmURL,
    realmURL.appendingPathExtension("lock"),
    realmURL.appendingPathExtension("note"),
    realmURL.appendingPathExtension("management")
]
for URL in realmURLs {
    do {
        try FileManager.default.removeItem(at: URL)
    } catch {
        // handle error
    }
}
  • Realm数据库会在当前的iOS应用程序中创建4个文件,realm数据库;realm lock文件;realm note文件;realm management文件
  • 使用Realm.Configuration.defaultConfiguration.fileURL可以打印出上述四个文件的位置
  • 可以通过配置Configuration文件修改Realm数据库的一些特性,比如数据迁移(下文)
  • 用FileManager删除当前已经存在的所有Realm数据库文件
var realm = try! Realm()
  • 创建一个Realm数据库链接,默认情况下链接的为上文中的realm数据库
  • 可以使用Configuration类为Realm配置其他属性,如加载外部数据库,加载内存数据,加载远程数据库,数据迁移等
  • 创建Model实例,修改Model实例,删除Model实例,增、删、改操作

//进行Realm数据库写入,在该范围内对Model的任何修改都会自动保存至Realm数据库中
try! realm.write {
    //创建User实例
    let newuser = User()
    //向Realm数据库,User表中添加一行
    realm.add(newuser)

    //为Car表添加一行
    let newcar = Car()
    newcar.brand = randombrands[Int.random(in: 0..<randombrands.count)]
    newcar.color = randomcolors[Int.random(in: 0..<randomcolors.count)]
    newcar.id = randomcarids[Int.random(in: 0..<randomcarids.count)]
    //创建外键,反向外键由Realm自动创建
    newuser.cars.append(newcar)
    realm.add(newcar)
    
    //在write域中,所有对Realm Model的修改都会自动保存
    //反射赋值
    newuser.setValue("18612345678", forKeyPath: "mobilePhoneNumber")
    //直接赋值
    newuser.userName = user
    newuser.portraitImage = UIImage(named: "\(Int.random(in: 1...15))")!.pngData()!
    newuser.qrcodeImage = UIImage(named: "\(Int.random(in: 1...15))")!.pngData()!
}
  • 创建一个表的行:Swift中创建一个Model的实例,如果要对列进行赋值只要只接修改属性值即可
  • 为表添加一行:使用add方法才会向Realm数据库中添加一样
  • 更新行数据:只要在write域中,所有对Realm Model的更新都是自动的
  • Realm还支持使用key-value(反射)的方式对Model中的属性进行赋值
  • 使用Realm.delete方法可以删除Model实例
  • 查询Model,查询、排序、分页操作

//查询,filter
//从数据库中获取当前登录用户的信息,User实例
currentUser = realm.objects(User.self).filter("userName = '别摸我咬你哦'").first!

//排序,sort
//获取所有可用预约,并按照创建时间进行排序
apps = realm.objects(Appointment.self).sorted(by: { $0.createDate > $1.createDate})

//限制查询数量,limit
//查询所有可用用户
let users = realm.objects(User.self)
//只获取前两个用户的数据
for user in 0..<2 {
    //do something
}

//分页操作,page,skip
let currentPage = P
let pageItemCount = N
let users = realm.objects(User.self)
//只获取第P页的N个用户数据
for user in P * N..< (P + 1) * N {
    //do something
}
  • Realm支持查询、排序、链接查询、有限查询操作
  • Realm使用懒加载(同C#的LINQ),只有当真正读取查询结果时才会加载数据,因此代码中currentUser和apps两行是不会产生延迟的,因为并没有真正的读取数据
  • Realm使用filter+predicate(断言)的方式进行查询,predicate为Apple查询语法,查看 Apple断言编程指南,Realm已经整理好了一个列表可以进行快速查询,Realm 断言帮助手册
  • 由于Realm使用懒加载进行查询,所以如果想要限定查询数量(limit)或者进行分页(page/skip),只要使用for循环即可

5. 数据库结构更新,迁移

let newSchemaVersion: UInt64 = 1
let config = Realm.Configuration(
    //设定当前数据库结果的版本号,默认从0开始,每次更新数据库结构都要增加1
    schemaVersion: newSchemaVersion,
    //数据库迁移模块
    migrationBlock: { migration, oldSchemaVersion in
        //对比当前APP中数据库版本号与新的版本号,如果较低则更新APP中的数据库结构
        if (oldSchemaVersion < newSchemaVersion) {
            // 如果不涉及到数据合并与重命名
            // 只是增加或者删除列,不需要进行任何操作
            // Realm会自动进行数据库结构更新
            // ... do nothing
            
            // 如果需要进行列的重命名则需要执行下列操作
            // 下列操作将User表中的'userName'列更新为'Name'列
            migration.renameProperty(onType: User.className(), from: "userName", to: "Name")
            
            // 如果需要进行列合并或拆分的操作则需要进行下列操作
            // oldObject:旧数据库结构中的所有列
            // newObject:新数据库结构中的所有列
            // Realm会自动对新数据库结构中的列进行赋值
            // 下列操作将Appointment中'startLocal'和'endLocal'列合并为'Route'列
            migration.enumerateObjects(ofType: User.className()) { oldObject, newObject in
                //拆分
                let startLocal = oldObject!["startLocal"] as! String
                let endLocal = oldObject!["endLocal"] as! String
                newObject!["Route"] = "from \(startLocal) to \(endLocal)"
            }
        }
})

//使用上述配置重新打开Realm数据库,Realm会根据配置自动迁移数据库
let realm = try! Realm(configuration: config)

6. 数据绑定,数据更新通知,观察者模式

暂时没用到:Realm Notification

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值