一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
- 本文主要介绍下关于
realmSwift以及它的拓展RxRealm的使用
1. realmSwift
realmSwift是
MongoDB 对移动端数据库的封装的一个SDK, RealmSwiftSDK 使移动应用程序能够访问存储在本地领域中的数据。或者,与函数、MongoDB 数据访问和身份验证等 MongoDB 领域服务进行交互。
感兴趣的可以看下官方文档
realmSwift这里我们简单的说明下
1.1 在Mac上查看realm文件
另外对于我们想要查看我们自己生成的realm文件
使用的是
App Store下载的Realm Browser的话打开是无法使用的
因为realm browser在2018年版本3.0.1之后就不再维护了,已经不能解析最新的.realm文件了
我们可以从最新的链接 下载
根据对应的平台下载
可以看到我们创建的realm文件
1.2 realmSwift中model的创建
我们看下在swift中使用realmSwift
通常我们按照官方文档进行创建
通常我们的model继承于 Objct
class CoffeeDrink: Object {
@Persisted var name = ""
@Persisted var hotOrCold: String?
@Persisted var rating = 0
}
我们可以指定主键:
主键是能确定一条记录的唯一标识,主要用于确定该数据的唯一性。主键字段必须唯一,必须非空,一个表中只能有一个主键,主键可以包含一个或多个字段。
我们可以指定默认的id:ObjectId为主键
或者重写func primaryKey()
或者这样
关于RealmSwift中Model有如下说明:
Realm 致力于平衡数据库读取的灵活性和性能。为了实现这个目标,在 Realm 中所存储的信息的各个方面都有基本的限制。例如:
(1)类名称的长度最大只能存储 57 个 UTF8 字符。
(2)属性名称的长度最大只能支持 63 个 UTF8 字符。
(3)NSData 以及 String 属性不能保存超过 16 MB 大小的数据。如果要存储大量的数据,可通过将其分解为16MB 大小的块,或者直接存储在文件系统中,然后将文件路径存储在 Realm 中。如果您的应用试图存储一个大于 16MB 的单一属性,系统将在运行时抛出异常。
(4)对字符串进行排序以及不区分大小写查询只支持“基础拉丁字符集”、“拉丁字符补充集”、“拉丁文扩展字符集 A” 以及”拉丁文扩展字符集 B“(UTF-8 的范围在 0~591 之间)。
1.3 创建默认Realm对象
在仅限本地的领域数据库中,打开领域的最简单选项是省略配置参数,该参数使用默认领域:
// Open the local-only default realm
let localRealm = try! Realm()
可以使用Realm() 初始化程序打开一个领域。如果省略Realm.Configuration参数,
将打开默认领域。
// Open the default realm
let defaultRealm = try! Realm()
// Open the realm with a specific file URL, for example a username
let username = "GordonCole"
var config = Realm.Configuration.defaultConfiguration
config.fileURL!.deleteLastPathComponent()
config.fileURL!.appendPathComponent(username)
config.fileURL!.appendPathExtension("realm")
let realm = try! Realm(configuration: config)
配置
// Open the realm with a specific in-memory identifier.
let identifier = "MyRealm"
let config = Realm.Configuration(
inMemoryIdentifier: identifier)
// Open the realm
let realm = try! Realm(configuration: config)
1.4 添加
通常会通过Realm.add(_:update:)
// Instantiate the class. For convenience, you can initialize
// objects from dictionaries with appropriate keys and values.
let dog = Dog(value: ["name": "Max", "age": 5])
let realm = try! Realm()
// Open a thread-safe transaction.
try! realm.write {
// Add the instance to the realm.
realm.add(dog)
}
- 对
json数据进行写入
// Specify a dog toy in JSON
let data = "{\"name\": \"Tennis ball\"}".data(using: .utf8)!
let realm = try! Realm()
// Insert from data containing JSON
try! realm.write {
let json = try! JSONSerialization.jsonObject(with: data, options: [])
realm.create(DogToy.self, value: json)
}
upsertupsert根据对象是否已经存在来插入或更新对象。Upserts 要求数据模型有一个主键 要更新对象,请调用Realm.add(_:update:)并将第二个参数update policy设置为.modified。
let realm = try! Realm()
try! realm.write {
let person1 = Person(value: ["id": 1234, "name": "Jones"])
// Add a new person to the realm. Since nobody with ID 1234
// has been added yet, this adds the instance to the realm.
realm.add(person1, update: .modified)
let person2 = Person(value: ["id": 1234, "name": "Bowie"])
// Judging by the ID, it's the same person, just with a
// different name. When `update` is:
// - .modified: update the fields that have changed.
// - .all: replace all of the fields regardless of
// whether they've changed.
// - .error: throw an exception if a key with the same
// primary key already exists.
realm.add(person2, update: .modified)
}
1.5 删除
- delete
要从表中删除对象,请将对象传递给写入事务中的
Realm.delete(_:)
try! realm.write {
// Delete the instance from the realm.
realm.delete(dog)
}
从领域中删除对象后,您将无法访问或修改该对象。如果您尝试使用已删除的对象,Realm Database 会抛出错误。
- 删除多个对象
let realm = try! Realm()
try! realm.write {
// Find dogs younger than 2 years old.
let puppies = realm.objects(Dog.self).where {
$0.age < 2
}
// Delete the objects in the collection from the realm.
realm.delete(puppies)
}
- 删除
特定类型的所有对象
let realm = try! Realm()
try! realm.write {
// Delete all instances of Dog from the realm.
let allDogs = realm.objects(Dog.self)
realm.delete(allDogs)
}
- 删除特定类型的所有对象
要从领域中删除所有对象,请 在写入事务中调用
Realm.deleteAll()这会清除所有对象实例的领域,但不会影响领域的模式。
let realm = try! Realm()
try! realm.write {
// Delete all objects from the realm.
realm.deleteAll()
}
1.6 修改
您可以在写入事务中修改 Realm 对象的属性,就像更新任何其他 Swift 或 Objective-C 对象一样。
let realm = try! Realm()
// Get a dog to update
let dog = realm.objects(Dog.self).first!
// Open a thread-safe transaction
try! realm.write {
// Update some properties on the instance.
// These changes are saved to the realm
dog.name = "Wolfie"
dog.age += 1
}
- 所有对象的话
let realm = try! Realm()
let allDogs = realm.objects(Dog.self)
try! realm.write {
allDogs.first?.setValue("Sparky", forKey: "name")
// Move the dogs to Toronto for vacation
allDogs.setValue("Toronto", forKey: "currentCity")
}
1.7 查询
通常会使用realm.object来进行查询
let realm = try! Realm()
// Access all dogs in the realm
let dogs = realm.objects(Dog.self)
这将返回一个Results对象,该对象表示领域中给定类型的所有对象。
- 过滤查询
过滤器根据一个或多个对象属性的值选择结果子集。
Realm数据库提供了一个功能齐全的查询引擎,您可以使用它来定义过滤器。
let realm = try! Realm()
// Access all dogs in the realm
let dogs = realm.objects(Dog.self)
// Query by age
let puppies = dogs.where {
$0.age < 2
}
// Query by person
let dogsWithoutFavoriteToy = dogs.where {
$0.favoriteToy == nil
}
// Query by person's name
let dogsWhoLikeTennisBalls = dogs.where {
$0.favoriteToy.name == "Tennis ball"
}
- 通过
primaryKey查询
let realm = try! Realm()
let specificPerson = realm.object(ofType: Person.self, forPrimaryKey: 12345)
2. RxRealm
对于我们realmSwift,就如上面介绍的具体复杂的可以参考官方文档。RxSwift也是对Realm进行了封装,为RxRealm。
我们导入RxRealm
pod "RxRealm"
主要就是2个文件,对RealmSwift的一些操作进行封装从而可以让我们可以订阅,结合RxSwift方便操作。
2.1 初始化
初始化也是类似的使用进行默认初始化
let realm = try! Realm()
使用config进行配置
let username = "GordonCole"
var config = Realm.Configuration.defaultConfiguration
config.fileURL!.deleteLastPathComponent()
config.fileURL!.appendPathComponent(username)
config.fileURL!.appendPathExtension("realm")
let realm = try! Realm(configuration: config)
2.2 集合类的操作
- collection
这些类型通常用于从 Realm 移动数据库加载和观察对象集合。
Results``List``LinkingObjects``AnyRealmCollectionObservable.collection(from:synchronousStart:)
每次集合更改时发出一个事件:
let realm = try! Realm()
let laps = realm.objects(Lap.self)
Observable.collection(from: laps)
.map {
laps in "\(laps.count) laps"
}
.subscribe(onNext: { text in
print(text)
})
array每次更改都会获取Realm 集合的快照并将其转换为数组值(例如,如果您想在集合上使用数组方法):
let realm = try! Realm()
let laps = realm.objects(Lap.self)
Observable.array(from: laps)
.map { array in
return array.prefix(3) //slice of first 3 items
}
.subscribe(onNext: { text in
print(text)
})
changeset每次集合更改时发出并提供已删除、插入或更新的确切索引:
let realm = try! Realm()
let laps = realm.objects(Lap.self)
Observable.changeset(from: laps)
.subscribe(onNext: { results, changes in
if let changes = changes {
// it's an update
print(results)
print("deleted: \(changes.deleted)")
print("inserted: \(changes.inserted)")
print("updated: \(changes.updated)")
} else {
// it's the initial data
print(results)
}
})
2.3 观察单个对象
有一个单独的 API 可以更轻松地观察单个对象:
Observable.from(object: ticker)
.map { ticker -> String in
return "\(ticker.ticks) ticks"
}
.bindTo(footer.rx.text)
2.4 写入操作
我们制定的realm对象写入
rx.add()
let realm = try! Realm()
let messages = [Message("hello"), Message("world")]
Observable.from(messages)
.subscribe(realm.rx.add())
请注意,这将保留你的 Realm对象 直到Observable完成或出错。
Realm.rx.add()默认的realm,您可以将其留给RxRealm来获取您订阅的任何线程上的默认Realm并向其写入对象:
let messages = [Message("hello"), Message("world")]
Observable.from(messages)
.subscribe(Realm.rx.add())
- 自定义的
configuration
var config = Realm.Configuration()
/* custom configuration settings */
let messages = [Message("hello"), Message("world")]
Observable.from(messages)
.observeOn( /* you can switch threads here */ )
.subscribe(Realm.rx.add(configuration: config, onError: {elements, error in
if let elements = elements {
print("Error \(error.localizedDescription) while saving objects \(String(describing: elements))")
} else {
print("Error \(error.localizedDescription) while opening realm.")
}
}))
2.5 删除操作
rx.delete()和添加类似,也是这将保留您的realm, 直到Observable完成或出错。
let realm = try! Realm()
let messages = realm.objects(Message.self)
Observable.from(messages)
.subscribe(realm.rx.delete())
3. 总结
以上就是关于RealmSwift和RxRealm的使用,值得注意的是在线程中打开Realm()后,如果保存了该实例对象,在宁外一个线程使用该对象会报错,我们应在同一线程使用该实例对象,或者重新实例化。