RxRealm

Carthage Compatible Version Swift Package Manager compatible License Platform

这个库是 RealmSwift ( Realm 文档 ) 的一个轻量级封装。

目录

  1. 观察对象集合
  2. 观察单个对象
  3. 写入事务
  4. 自动绑定表格和集合视图
  5. 示例应用

观察对象集合

RxRealm 可以用于从 Results, List, LinkingObjectsAnyRealmCollection 类型的对象创建 Observable。 这些类型通常用于从 Realm 移动数据库加载和观察对象集合。

Observable.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)
  })

以上代码会在每次添加或从数据库中删除 lap 时打印出 "X laps"。如果您将 synchronousStart 设置为 true(默认值),则第一个元素将同步发出 - 例如,当您绑定 UI 时,异步通知可能无法传递。

Observable.array(from:synchronousStart:)

每次更改时,获取 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)
  })
Observable.changeset(from:synchronousStart:)

每次集合更改时发出,并提供已删除、插入或更新的确切索引

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)
    }
  })
Observable.arrayWithChangeset(from:synchronousStart:)

结合 Observable.array(from:)Observable.changeset(from:) 的结果,返回一个 Observable<Array<T>, RealmChangeset?>

let realm = try! Realm()
let laps = realm.objects(Lap.self))

Observable.arrayWithChangeset(from: laps)
  .subscribe(onNext: { array, changes in
    if let changes = changes {
    // it's an update
    print(array.first)
    print("deleted: \(changes.deleted)")
    print("inserted: \(changes.inserted)")
    print("updated: \(changes.updated)")
  } else {
    // it's the initial data
    print(array)
  }
  })

观察单个对象

有一个单独的 API 使观察单个对象更容易

Observable.from(object: ticker)
    .map { ticker -> String in
        return "\(ticker.ticks) ticks"
    }
    .bindTo(footer.rx.text)

此 API 在底层使用 Realm 对象通知 来监听更改。

默认情况下,此方法将发出对象初始状态作为其第一个 next 事件。 您可以使用 emitInitialValue 参数并将其设置为 false 来禁用此行为。

最后,您可以设置哪些属性的更改构成您想要观察的对象更改

Observable.from(object: ticker, properties: ["name", "id", "family"]) ...

写入事务

rx.add()

将对象写入现有 Realm 引用。 您可以将新创建的对象添加到已初始化的 Realm 中

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())
Realm.rx.add(configuration:)

写入自定义 Realm。 如果您想切换线程并且不使用默认 Realm,请提供一个 Realm.Configuration。 您还可以为观察者提供一个错误处理程序,以便在创建 realm 引用或写入事务引发错误时调用它

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.")
    }
  }))

如果您想手动在不同的线程上创建一个 Realm,以便您可以处理错误,您也可以这样做

let messages = [Message("hello"), Message("world")]

Observable.from(messages)
  .observeOn( /* you can switch threads here */ )
  .subscribe(onNext: {messages in
    let realm = try! Realm()
    try! realm.write {
      realm.add(messages)
    }
  })
rx.delete()

从现有 realm 引用中删除对象

let realm = try! Realm()
let messages = realm.objects(Message.self)
Observable.from(messages)
  .subscribe(realm.rx.delete())

请注意,这将保留您的 realm,直到 Observable 完成或出错。

Realm.rx.delete()

自动从对象的 realm 中删除。您可以让 RxRealm 从第一个对象中获取 Realm 并使用它

Observable.from(someCollectionOfPersistedObjects)
  .subscribe(Realm.rx.delete())

自动绑定表格和集合视图

RxRealm 不依赖于 UIKit/Cocoa,并且不提供将 Realm 集合绑定到 UI 组件的内置方法。

a) 非动画绑定

您可以使用内置的 RxCocoa bindTo(_:) 方法,该方法会自动从您的 Realm 结果驱动您的表格视图

Observable.from( [Realm collection] )
  .bindTo(tableView.rx.items) {tv, ip, element in
    let cell = tv.dequeueReusableCell(withIdentifier: "Cell")!
    cell.textLabel?.text = element.text
    return cell
  }
  .addDisposableTo(bag)

b) 使用 RxRealmDataSources 进行动画绑定

单独的库 RxRealmDataSources 模仿了 RxSwift 的默认数据源库行为。

RxRealmDataSources 允许您将 Realm 对象的 observable 集合直接绑定到表格或集合视图

// create data source
let dataSource = RxTableViewRealmDataSource<Lap>(
  cellIdentifier: "Cell", cellType: PersonCell.self) {cell, ip, lap in
    cell.customLabel.text = "\(ip.row). \(lap.text)"
}

// RxRealm to get Observable<Results>
let realm = try! Realm()
let lapsList = realm.objects(Timer.self).first!.laps
let laps = Observable.changeset(from: lapsList)

// bind to table view
laps
  .bindTo(tableView.rx.realmChanges(dataSource))
  .addDisposableTo(bag)

数据源将通过动画反映到表格视图的所有更改

RxRealm animated changes

如果您想了解更多关于动画更改之外的功能,请查看 RxRealmDataSources README

示例应用

要运行示例项目,请克隆存储库,并首先从 Example 目录运行 pod install。 该应用程序使用 RxSwift、RxCocoa 使用 RealmSwift、RxRealm 来观察来自 Realm 的 Results。

此外,欢迎您查看示例应用程序的 RxRealmTests 文件夹,其中包含该库的单元测试。

安装

此库依赖于 RxSwiftRealmSwift 1.0+。

CocoaPods

RxRealm 需要 CocoaPods 1.1.x 或更高版本。

RxRealm 可通过 CocoaPods 获得。 要安装它,只需将以下行添加到您的 Podfile 中

pod "RxRealm"

Carthage

要使用 Carthage 将 RxRealm 集成到您的 Xcode 项目中,请在您的 Cartfile 中指定它

github "RxSwiftCommunity/RxRealm"

运行 carthage update 以构建框架并将构建的 RxRealm.framework 拖到您的 Xcode 项目中。

Swift Package Manager

在您的 Package.swift 中

let package = Package(
  name: "Example",
  dependencies: [
    .package(url: "https://github.com/RxSwiftCommunity/RxRealm.git", from: "1.0.1")
  ],
  targets: [
    .target(name: "Example", dependencies: ["RxRealm"])
  ]
)

TODO

许可证

此库属于 RxSwiftCommunity。 维护者是 Marin Todorov

RxRealm 在 MIT 许可证下可用。 有关更多信息,请参见 LICENSE 文件。