• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

RealmSwift

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

先决条件

  • XCode 9.2或更高版本
  • iOS 8或更高版本的目标,macOS 10.9或更高版本,或任何版本的tvOS或watchOS

安装

  1. 安装CocoaPods 1.1.0或更高版本。
  2. 运行pod repo update以使CocoaPods了解最新的Realm版本。
  3. 在你Podfile,添加use_frameworks!pod 'RealmSwift'你的主和测试目标。
  4. 从命令行运行pod install
  5. 使用.xcworkspaceCocoaPods生成文件来处理您的项目!

入门

如果您希望使用Objective-C中的 Realm ,或者使用混合的Objective-C和Swift应用程序,请参阅Realm Objective-CRealm Objective-C和Realm Swift API不可互操作,不支持它们一起使用。

Realm Swift使您能够以安全,持久和快速的方式有效地编写应用程序的模型层。这是它的样子:

 1 // Define your models like regular Swift classes
 2 class Dog: Object {
 3     @objc dynamic var name = ""
 4     @objc dynamic var age = 0
 5 }
 6 class Person: Object {
 7     @objc dynamic var name = ""
 8     @objc dynamic var picture: Data? = nil // optionals supported
 9     let dogs = List<Dog>()
10 }
11 
12 // Use them like regular Swift objects
13 let myDog = Dog()
14 myDog.name = "Rex"
15 myDog.age = 1
16 print("name of dog: \(myDog.name)")
17 
18 // Get the default Realm
19 let realm = try! Realm()
20 
21 // Query Realm for all dogs less than 2 years old
22 let puppies = realm.objects(Dog.self).filter("age < 2")
23 puppies.count // => 0 because no dogs have been added to the Realm yet
24 
25 // Persist your data easily
26 try! realm.write {
27     realm.add(myDog)
28 }
29 
30 // Queries are updated in realtime
31 puppies.count // => 1
32 
33 // Query and update from any thread
34 DispatchQueue(label: "background").async {
35     autoreleasepool {
36         let realm = try! Realm()
37         let theDog = realm.objects(Dog.self).filter("age == 1").first
38         try! realm.write {
39             theDog!.age = 3
40         }
41     }
42 }

Realm Studio

Realm Studio是我们的首选开发人员工具,可以轻松管理Realm数据库和Realm平台。使用Realm Studio,您可以打开和编辑本地和同步的域,并管理任何Realm Object Server实例。它支持Mac,Windows和Linux。

使用菜单项“ 工具”>“生成演示数据库”创建包含示例数据的测试数据库

如果您在查找应用程序的Realm文件时需要帮助,请查看此StackOverflow答案以获取详细说明。

例子

您可以在我们的发布zip找到iOS和OS X的示例应用程序examples/,演示如何使用Realm的许多功能,如迁移,如何使用它UITableViewController,加密,命令行工具等等。

使用Realm框架

在Swift源文件的顶部,用于import RealmSwift导入Realm Swift并使其可用于您的代码。这就是你开始所需要的一切!

tvOS

因为在tvOS上禁止写入“Documents”目录,所以默认的Realm位置设置为NSCachesDirectory但是,请注意tvOS可以随时清除“Caches”目录中的文件,因此我们建议您依赖Realm作为可重建的缓存,而不是存储重要的用户数据。

如果您想在tvOS应用程序和电视服务扩展(例如Top Shelf扩展)之间共享Realm文件,则必须使用Library/Caches/共享容器中的应用程序组目录。

1 let fileURL = FileManager.default
2     .containerURL(forSecurityApplicationGroupIdentifier: "group.io.realm.examples.extension")!
3     .appendingPathComponent("Library/Caches/default.realm")

您还可以在应用中捆绑预构建的Realm文件但是,请务必遵守App Store指南,将您的应用保持在200MB以下。请浏览我们的tvOS示例,了解示例如何使用Realm作为离线缓存或预加载数据的示例tvOS应用程序。

使用Realm与后台应用程序刷新

在iOS 8及更高版本中,NSFileProtection只要设备被锁定,应用程序内的文件就会自动加密如果您的应用程序在设备被锁定时尝试执行涉及Realm的任何工作,并且NSFileProtection您的Realm文件属性设置为加密它们(默认情况下就是这种情况),open() failed: Operation not permitted则会引发异常。

为了解决这个问题,有必要确保应用于Realm文件本身及其辅助文件的文件保护属性降级为不太严格的文件保护属性,即使在设备被锁定时也允许文件访问,例如NSFileProtectionCompleteUntilFirstUserAuthentication

如果您选择以这种方式选择退出完整的iOS文件加密,我们建议您使用Realm自己的内置加密来确保您的数据仍然得到妥善保护。

由于辅助文件有时可以在操作过程中延迟创建和删除,因此我们建议您将文件保护属性应用于包含这些Realm文件的父文件夹。这将确保该属性正确应用于所有相关Realm文件,无论其创建时间如何。

1 let realm = try! Realm()
2 
3 // Get our Realm file's parent directory
4 let folderPath = realm.configuration.fileURL!.deletingLastPathComponent().path
5 
6 // Disable file protection for this directory
7 try! FileManager.default.setAttributes([FileAttributeKey(rawValue: NSFileProtectionKey): NSFileProtectionNone],
8                                        ofItemAtPath: folderPath)

三界

一个境界是一种境界移动数据库容器的一个实例。

有关Realms的详细讨论,请阅读The Realm Data Model有关创建和管理领域的信息,请参阅

打开本地领域

要打开Realm,请实例化一个新Realm对象:

1 let realm = try! Realm()
2 
3 try! realm.write {
4     realm.add(myDog)
5 }

这会实例化默认的Realm

配置本地领域

通过创建实例Realm.Configuration并设置适当的属性,在打开Realm之前配置它创建和自定义配置值允许您自定义以及其他方面:

  • 本地Realm文件位置的路径
  • 迁移功能,如果一个领域的模式和版本之间的更改必须更新
  • 配置压缩功能以确保有效利用磁盘空间。

可以在Realm(configuration: config)每次需要Realm实例时传递配置,也可以将配置设置为默认Realm实例Realm.Configuration.defaultConfiguration = config

例如,假设您有一个应用程序,用户必须登录到您的Web后端,并且您希望支持在帐户之间快速切换。您可以通过执行以下操作为每个帐户提供自己的Realm文件,该文件将用作默认Realm:

1 func setDefaultRealmForUser(username: String) {
2     var config = Realm.Configuration()
3 
4     // Use the default directory, but replace the filename with the username
5     config.fileURL = config.fileURL!.deletingLastPathComponent().appendingPathComponent("\(username).realm")
6 
7     // Set this as the configuration used for the default Realm
8     Realm.Configuration.defaultConfiguration = config
9 }

您可以拥有多个配置对象,因此您可以独立控制每个Realm的版本,架构和位置。

 1 let config = Realm.Configuration(
 2     // Get the URL to the bundled file
 3     fileURL: Bundle.main.url(forResource: "MyBundledData", withExtension: "realm"),
 4     // Open the file in read-only mode as application bundles are not writeable
 5     readOnly: true)
 6 
 7 // Open the Realm with the configuration
 8 let realm = try! Realm(configuration: config)
 9 
10 // Read some data from the bundled Realm
11 let results = realm.objects(Dog.self).filter("age > 5")

存储可写Realm文件的最常见位置是iOS上的“Documents”目录和macOS上的“Application Support”目录。请尊重Apple的iOS数据存储指南,该指南建议如果应用程序可以重新生成的文档应存储在<Application_Home>/Library/Caches目录中。如果使用自定义URL初始化Realm,则必须描述具有写入权限的位置。

默认领域

到目前为止,您可能已经注意到我们realm通过调用初始化了对变量的访问Realm()该方法返回一个Realm对象,对象映射到default.realm应用程序的Documents文件夹(iOS)或Application Support文件夹(macOS)中指定的文件。

打开同步领域

您是否希望使用Realm Mobile Platform同步所有Realm数据库?所有与同步相关的文档已移至我们的平台文档中

内存领域

通过设置inMemoryIdentifier而不是fileURLon Realm.Configuration,您可以创建一个完全在内存中运行而不会持久保存到磁盘的Realm。设置inMemoryIdentifier将为零fileURL(反之亦然)。

let realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "MyInMemoryRealm"))

内存领域不会跨应用程序启动保存数据,但Realm的所有其他功能将按预期工作,包括查询,关系和线程安全。如果您需要灵活的数据访问而没有磁盘持久性的开销,这是一个有用的选项。

内存领域在临时目录中创建多个文件,用于协调跨进程通知等事务。实际上没有数据写入文件,除非由于内存压力操作系统需要交换到磁盘。

注意:当具有特定标识符的所有内存中Realm实例超出范围而没有引用时,该Realm中的所有数据都将被删除。我们建议您在应用程序的生命周期内保留对任何内存领域的强引用。(对于磁盘领域,这不是必需的。)

错误处理

与任何磁盘I / O操作一样,Realm如果资源受到限制,创建实例有时可能会失败。实际上,这只能在第一次在给定线程上创建Realm实例时发生。从同一个线程对Realm的后续访问将重用高速缓存的实例并始终成功。

要在首次访问给定线程上的Realm时处理错误,请使用Swift的内置错误处理机制:

1 do {
2     let realm = try Realm()
3 } catch let error as NSError {
4     // handle error
5 }

辅助领域文件

除标准.realm文件外,Realm还为其自己的内部操作生成并维护其他文件和目录。

  • .realm.lock - 资源锁的锁文件。
  • .realm.management - 进程间锁定文件的目录。
  • .realm.note - 用于通知的命名管道。

这些文件对.realm数据库文件没有任何影响,如果删除或替换父数据库文件,则不会导致任何错误行为。

报告领域的问题,请一定要包括这些辅助文件与主一起.realm的文件,因为它们包含用于调试的信息。

捆绑一个境界

通常使用初始数据为应用程序设定种子,使其在首次启动时立即可供您的用户使用。这是如何做到这一点:

  1. 首先,填充领域。您应该使用与最终发货应用相同的数据模型来创建Realm,并使用您希望与应用捆绑在一起的数据填充它。由于Realm文件是跨平台的,您可以使用macOS应用程序(请参阅我们的JSONImport示例)或在模拟器中运行的iOS应用程序。
  2. 在您生成此Realm文件的代码中,您应该通过制作文件的压缩副本来完成(请参阅参考资料Realm().writeCopyToPath(_:encryptionKey:))。这将减少Realm的文件大小,使您的最终应用程序更轻松地为您的用户下载。
  3. 将Realm文件的新压缩副本拖到最终应用程序的Xcode Project Navigator中。
  4. 转到Xcode中的app target的构建阶段选项卡,并将Realm文件添加到“Copy Bundle Resources”构建阶段。
  5. 此时,您的应用可以访问捆绑的Realm文件。您可以使用找到它的路径NSBundle.main.pathForResource(_:ofType:)
  6. 如果捆绑的领域包含您不需要修改固定的数据,你可以直接从束路径设置中打开它readOnly = true的上Realm.Configuration对象。否则,如果它是您要修改的初始数据,则可以使用将捆绑的文件复制到应用程序的Documents目录中NSFileManager.default.copyItemAtPath(_:toPath:)

您可以参考我们的迁移示例应用程序,以获取有关如何使用捆绑的Realm文件的示例。

类子集

在某些情况下,您可能希望限制哪些类可以存储在特定领域中。例如,如果您有两个团队在应用程序的不同组件上工作,这两个组件都在内部使用Realm,那么您可能不希望必须协调它们之间的迁移你可以通过设置objectTypes属性来做到这一点Realm.Configuration

1 let config = Realm.Configuration(objectTypes: [MyClass.self, MyOtherClass.self])
2 let realm = try! Realm(configuration: config)

压缩领域

Realm的工作方式是Realm文件的大小始终大于存储在其中的对象的总大小。请参阅我们关于线程的文档,了解为什么这种架构能够实现Realm的一些出色性能,并发性和安全性优势。

为了避免进行昂贵的系统调用,Realm文件很少在运行时缩小。相反,它们以特定的大小增量增长,新数据被写入文件内跟踪的未使用空间内。但是,可能存在Realm文件的重要部分由未使用的空间组成的情况。为了解决这个问题,您可以shouldCompactOnLaunch在Realm的配置对象上设置block属性,以确定在第一次打开时是否应该压缩Realm文件。例如:

 1 let config = Realm.Configuration(shouldCompactOnLaunch: { totalBytes, usedBytes in
 2     // totalBytes refers to the size of the file on disk in bytes (data + free space)
 3     // usedBytes refers to the number of bytes used by data in the file
 4 
 5     // Compact if the file is over 100MB in size and less than 50% 'used'
 6     let oneHundredMB = 100 * 1024 * 1024
 7     return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
 8 })
 9 do {
10     // Realm is compacted on the first open if the configuration block conditions were met.
11     let realm = try Realm(configuration: config)
12 } catch {
13     // handle error compacting or opening Realm
14 }

压缩操作通过读取Realm文件的全部内容,将其重写到不同位置的新文件,然后替换原始文件来工作。根据文件中的数据量,这可能是一项昂贵的操作。

我们鼓励您尝试使用这些数字来确定在经常执行压缩和让Realm文件变得过大之间取得良好平衡。

最后,如果另一个进程正在访问Realm,即使满足配置块的条件,也会跳过压缩。这是因为在访问Realm时无法安全地执行压缩。

shouldCompactOnLaunch同步域不支持设置块。这是因为压缩不会保留事务日志,必须保留事务日志以进行同步。

删除Realm文件

在某些情况下,例如清除缓存或重置整个数据集,从磁盘中完全删除Realm文件可能是合适的。

因为Realm避免将数据复制到内存中,除非绝对需要,所以Realm管理的所有对象都包含对磁盘上文件的引用,并且必须先释放它才能安全删除文件。这包括从读取(或加入)的所有对象的境界,所有ListResults以及ThreadSafeReference目的和Realm本身。

实际上,这意味着删除Realm文件应该在应用程序启动之前在打开Realm之前完成,或者在仅在显式自动释放池中打开Realm之后完成,这样可以确保所有Realm对象都已被释放。

最后,虽然不是绝对必要,但您应该删除辅助Realm文件以及主Realm文件以完全清除所有相关文件。

 1 autoreleasepool {
 2     // all Realm usage here
 3 }
 4 let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
 5 let realmURLs = [
 6     realmURL,
 7     realmURL.appendingPathExtension("lock"),
 8     realmURL.appendingPathExtension("note"),
 9     realmURL.appendingPathExtension("management")
10 ]
11 for URL in realmURLs {
12     do {
13         try FileManager.default.removeItem(at: URL)
14     } catch {
15         // handle error
16     }
17 }

楷模

领域数据模型被定义为具有常规属性的常规Swift类。创建一个,只是子类Object或现有的Realm模型类。领域模型对象的功能大多与其他任何Swift对象一样。您可以在它们上定义自己的方法,使它们符合协议,并像使用任何其他对象一样使用它们。主要限制是您只能在创建它的线程上使用对象。

关系和嵌套的数据结构由包括目标类型的属性或建模List小号的对象的类型的列表。List实例也可用于建模原始值的集合(例如,字符串或整数数组)。

 1 import RealmSwift
 2 
 3 // Dog model
 4 class Dog: Object {
 5     @objc dynamic var name = ""
 6     @objc dynamic var owner: Person? // Properties can be optional
 7 }
 8 
 9 // Person model
10 class Person: Object {
11     @objc dynamic var name = ""
12     @objc dynamic var birthdate = Date(timeIntervalSince1970: 1)
13     let dogs = List<Dog>()
14 }

由于Realm在启动时会解析代码中定义的所有模型,因此它们必须全部有效,即使它们从未使用过。

当使用Swift中的Realm时,该Swift.reflect(_:)函数用于确定有关模型的信息,这需要调用init()成功。这意味着所有非可选属性都必须具有默认值。

有关详细信息,请参阅我们的API文档Object

支持的属性类型

域支持以下属性类型:BoolIntInt8Int16Int32Int64DoubleFloatStringDate,和Data

CGFloat 不鼓励使用属性,因为类型不是平台无关的。

StringDate并且Data属性可以是可选的。Object属性必须是可选的。存储可选数字是使用RealmOptional

必需的属性

StringDateData属性可以使用标准Swift语法声明为可选或必需(非可选)。使用类型声明可选的数字类型RealmOptional

 1 class Person: Object {
 2     // Optional string property, defaulting to nil
 3     @objc dynamic var name: String? = nil
 4 
 5     // Optional int property, defaulting to nil
 6     // RealmOptional properties should always be declared with `let`,
 7     // as assigning to them directly will not work as desired
 8     let age = RealmOptional<Int>()
 9 }
10 
11 let realm = try! Realm()
12 try! realm.write() {
13     var person = realm.create(Person.self, value: ["Jane", 27])
14     // Reading from or modifying a `RealmOptional` is done via the `value` property
15     person.age.value = 28
16 }

RealmOptional支持IntFloatDoubleBool,和所有的大小版本IntInt8Int16Int32Int64)。

主键

覆盖Object.primaryKey()以设置模型的主键。声明主键可以有效地查找和更新对象,并为每个值强制实现唯一性。将具有主键的对象添加到Realm后,无法更改主键。

1 class Person: Object {
2     @objc dynamic var id = 0
3     @objc dynamic var name = ""
4 
5     override static func primaryKey() -> String? {
6         return "id"
7     }
8 }

索引属性

要索引属性,请覆盖Object.indexedProperties()与主键一样,索引使写入速度稍慢,但使查询使用相等性和IN运算符更快。(它还会使您的Realm文件略大,以存储索引。)最好只在优化特定情况下的读取性能时添加索引。

1 class Book: Object {
2     @objc dynamic var price = 0
3     @objc dynamic var title = ""
4 
5     override static func indexedProperties() -> [String] {
6         return ["title"]
7     }
8 }

Realm支持对字符串,整数,布尔值和Date属性进行索引

忽略属性

如果您不想将模型中的字段保存到其Realm,请覆盖Object.ignoredProperties()领域不会干扰这些属性的正常运行; 他们将得到伊娃的支持,你可以自由地覆盖他们的二传手和吸气者。

 1 class Person: Object {
 2     @objc dynamic var tmpID = 0
 3     var name: String { // read-only properties are automatically ignored
 4         return "\(firstName) \(lastName)"
 5     }
 6     @objc dynamic var firstName = ""
 7     @objc dynamic var lastName = ""
 8 
 9     override static func ignoredProperties() -> [String] {
10         return ["tmpID"]
11     }
12 }

忽略的属性与普通属性完全相同。它们不支持任何特定于Realm的功能(例如,它们不能在查询中使用,也不会触发通知)。仍然可以使用KVO观察它们。

属性属性

领域模型属性必须具有该@objc dynamic var属性才能成为底层数据库数据的访问者。请注意,如果将类声明为@objcMembers(Swift 4或更高版本),则可以将各个属性声明为dynamic var

有三种例外情况:LinkingObjectsListRealmOptional这些属性不能声明为动态,因为通用属性无法在Objective-C运行时中表示,后者用于动态分派dynamic属性。应始终使用声明这些属性let

财产备忘单

此表提供了声明模型属性的便捷参考。

类型 非可选 可选的
布尔 @objc dynamic var value = false let value = RealmOptional<Bool>()
诠释 @objc dynamic var value = 0 let value = RealmOptional<Int>()
浮动 @objc dynamic var value: Float = 0.0 let value = RealmOptional<Float>()
@objc dynamic var value: Double = 0.0 let value = RealmOptional<Double>()
@objc dynamic var value = "" @objc dynamic var value: String? = nil
数据 @objc dynamic var value = Data() @objc dynamic var value: Data? = nil
日期 @objc dynamic var value = Date() @objc dynamic var value: Date? = nil
宾语 不适用:必须是可选的 @objc dynamic var value: Class?
名单 let value = List<Type>() 不适用:必须是非选择性的
LinkingObjects let value = LinkingObjects(fromType: Class.self, property: "property") 不适用:必须是非选择性的

使用Realm对象

自动更新对象

Object实例是实时的,自动更新基础数据的视图; 你永远不必刷新对象。修改对象的属性将立即反映在引用同一对象的任何其他实例中。

 1 let myDog = Dog()
 2 myDog.name = "Fido"
 3 myDog.age = 1
 4 
 5 try! realm.write {
 6     realm.add(myDog)
 7 }
 8 
 9 let myPuppy = realm.objects(Dog.self).filter("age == 1").first
10 try! realm.write {
11     myPuppy!.age = 2
12 }
13 
14 print("age of my dog: \(myDog.age)") // => 2

这不仅可以保持Realm的快速和高效,还可以使您的代


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
[Swift]LeetCode692.前K个高频单词|TopKFrequentWords发布时间:2022-07-13
下一篇:
ios (实用)模仿 Apple 教學範例,寫出一手好 Swift发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap