RealmSwift 初探
一下内容摘自文档
- Realm是一个跨平台的移动数据库引擎,目前支持
iOS、Android平台,同时支持Objective-C、Swift、Java、React Native、Xamarin等多种编程语言*Realm并不是对SQLite或者CoreData的简单封装, 是由核心数据引擎C++打造,是拥有独立的数据库存储引擎,可以方便、高效的完成数据库的各种操作
Realm Swift 能够让您以安全、稳定、迅速的方式,来高效编写引用的数据模型层。如下例所示:
// 定义模型的做法和定义常规 Swift 类的做法类似
class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var age = 0
}
class Person: Object {
@objc dynamic var name = ""
@objc dynamic var picture: Data? = nil // 支持可空值
let dogs = List<Dog>()
}
// 像常规 Swift 对象一样使用
let myDog = Dog()
myDog.name = "Rex"
myDog.age = 1
print("name of dog: \(myDog.name)")
// 获取默认的 Realm 数据库
let realm = try! Realm()
// 检索 Realm 数据库,找到小于 2 岁 的所有狗狗
let puppies = realm.objects(Dog.self).filter("age < 2")
puppies.count // => 0 因为目前还没有任何狗狗被添加到了 Realm 数据库中
// 数据存储十分简单
try! realm.write {
realm.add(myDog)
}
// 检索结果会实时更新
puppies.count // => 1
// 可以在任何一个线程中执行检索、更新操作
DispatchQueue(label: "background").async {
autoreleasepool {
let realm = try! Realm()
let theDog = realm.objects(Dog.self).filter("age == 1").first
try! realm.write {
theDog!.age = 3
}
}
}
安装
-
安装 CocoaPods 1.1.0 或者更高版本
- 执行 pod repo update,从而让 CocoaPods 更新至目前最新可用的 Realm 版本;
- 在您的 Podfile 中,将 use_frameworks! 和 pod 'RealmSwift' 添加到主应用目标和测试目标中;
- 在命令行中执行 pod install;
- 使用由 CocoaPods 生成的 .xcworkspace 文件来编写工程。
从AppStore下载Realm Brower可以使数据库变得图形化
使用
在 Swift 源文件的顶部,使用 import RealmSwift 来导入 Realm Swift,从而让其能够在代码中使用。 这样一切就准备妥当了!
使用带有后台应用刷新功能的 Realm
在 iOS 8 及其以上平台中,当设备锁定之后,应用内的文件会自动被 NSFileProtection 所加密。 如果您的应用试图在设备锁定、且 Realm 文件的 NSFileProtection 属性被设置为“允许加密”(默认配置)的时候,去执行任何涉及 Realm 操作的话,那么就会抛出一个 open() failed: Operation not permitted 异常。
为了解决这个问题,请确保将 Realm 文件本身以及其辅助文件两者的文件保护属性降级,比如说NSFileProtectionCompleteUntilFirstUserAuthentication,这样即便设备被锁定,文件仍然允许被访问。
如果您选择以这种方式摈弃完整的 iOS 文件加密机制的话,那么我们建议您使用Realm 内置的加密机制,从而确保您的数据仍能够得到正确保护。
由于辅助文件有些时候可能会延迟创建,或者在中间操作中被删除,因此我们建议您将文件保护属性应用到包含这些 Realm 文件的父文件夹中。 这将确保所有相关的 Realm 文件无论是何时所创建的,都能够应用此属性配置。
配置 Realm 数据库
在打开 Realm 数据库之前,可以对其进行配置。 通过创建一个 Realm.Configuration 的对象实例,然后配置相应的属性。 通过创建并自定义相关的配置值,使得您可以实现个性化的设置,包括如下方面:
- 对于本地 Realm 数据库而言,可以配置 Realm 文件在磁盘上的路径;
- 对于可同步 Realm 数据库而言,可以配置管理该 Realm 数据库的用户,以及 Realm 数据库在 Realm 对象服务器上的远程路径;
- 对于架构版本之间发生变化的 Realm 数据库而言,可以通过迁移功能来控制旧架构的 Realm 数据该如何更新到最新的架构。
- 对于存储的数据量过大、或者数据频繁发生变化的 Realm 数据库而言,可以通过压缩功能来控制 Realm 文件该如何实现压缩,从而确保能高效地利用磁盘空间。
要应用配置,可以在每次需要获取 Realm 实例的时候,通过向 Realm(configuration: config)方法传递该配置对象,或者通过 Realm.Configuration.defaultConfiguration = config 方法,将默认 Realm 数据库的默认配置设置为我们所需的配置。
例如,假设有一个应用要求用户必须要登录到 Web 后端服务器中,并且需要支持账户快速切换功能的话。 那么您可以通过以下代码,来为每个账户提供一个独立的 Realm 数据库,并且当前账户所使用的数据库将作为默认 Realm 数据库来使用:
func setDefaultRealmForUser(username: String) {
var config = Realm.Configuration()
// 使用默认的目录,但是请将文件名替换为用户名
config.fileURL = config.fileURL!.deletingLastPathComponent().appendingPathComponent("\(username).realm")
// 将该配置设置为默认 Realm 配置
Realm.Configuration.defaultConfiguration = config
}
打开可同步 Realm 数据库
Realm 对象服务器上的 Realm 数据库同样也可以使用 Realm.Configuration 和相关的工厂方法进行配置,这与之前创建本地 Realm 数据库的做法基本类似,只不过在 Realm.Configuration 中,需要将 syncConfiguration 属性设置为 SyncConfiguration。 可同步 Realm 数据库 (synchronized Realm) 可通过 URL 地址来进行定位。
// 创建配置
let syncServerURL = URL(string: "realm://localhost:9080/~/userRealm")!
let config = Realm.Configuration(syncConfiguration: SyncConfiguration(user: user, realmURL: syncServerURL))
// 打开远程 Realm 数据库
let realm = try! Realm(configuration: config)
// 任何对此 Realm 数据库所做的操作,都会同步到所有设备上!
异步打开 Realm 数据库
如果打开 Realm 数据库的操作需要耗费大量时间的话,比如说需要执行迁移、压缩 或者需要从可同步 Realm 数据库下载远程内容,那么建议使用 asyncOpen API。 这使得您可以在调度到指定队列之前,在后台线程中执行任意的初始化工作。 当可同步 Realm 数据库只能以只读权限打开的时候,那么必须使用 asyncOpen。
内存中 Realm 数据库
通过配置 Realm.Configuration 中的 inMemoryIdentifier 属性,而不是 fileURL 属性,这样就能够创建一个完全在内存中运行的 Realm 数据库 (in-memory Realm),它将不会存储在磁盘当中。 设置 inMemoryIdentifier 会将 fileURL 置为 nil(反之亦然)。
删除 Realm 文件
在某些情况下,例如清除缓存、或者重置整个数据集之类的操作,那么就可能需要从磁盘中将 Realm 文件给完全删除掉。
除非必要,否则 Realm 数据库会避免将数据复制到内存中,因此由 Realm 管理的所有对象都会包含磁盘上文件的引用,并且必须在文件被安全删除之前完成释放。 这包括从 Realm 读取到(或者添加到 Realm 中)的所有对象,包括所有 List、Results 和 ThreadSafeReference 对象,以及 Realm 本身。
实际上,这意味着对 Realm 文件的删除,要么在应用启动时、在打开 Realm 数据库之前完成,要么只在显式声明的自动释放池 中打开 Realm 数据库,然后在自动释放池后面进行删除。 这样才能够确保所有的 Realm 对象都能够成功释放。
最后,尽管不是必须的,不过您应当将 Realm 辅助文件连同 Realm 文件一起删除,以完全清除所有的相关文件。
autoreleasepool {
// 在这里进行所有的 Realm 操作
}
let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
let realmURLs = [
realmURL,
realmURL.appendingPathExtension("lock"),
realmURL.appendingPathExtension("note"),
realmURL.appendingPathExtension("management")
]
for URL in realmURLs {
do {
try FileManager.default.removeItem(at: URL)
} catch {
// 错误处理
}
}