RxSwift_v1.0笔记——21 RxRealm

RxSwift_v1.0笔记——21 RxRealm

很久以前,在一个遥远的平行宇宙,开发者开发app需要一个数据库,他们可以选择普遍但是啰嗦的Core Data,或者为SQLite创建自定义封装。然后Realm出现了,在应用程序中突然使用数据库变得轻而易举。

Realm中的数据库查询是“live”:结果集合的内容与任何数据库更改一起更新。 插入,修改或删除项目,您将立即看到“结果”对象中的更改。 此外,细粒度(fine-grained)通知可以提供有关Results对象中更改的详细信息。

List类型也是如此,它允许您构建对象集合,甚至在正在使用的单个对象也会自动更新其内容,同时应该对数据库进行更改。所有这一切使得Realm成为将这些动态变化暴露为observable序列的理想候选者!

RxRealm, https://github.com/RxSwiftCommunity/RxRealm ,是RxSwiftCommunity组织下的另一个项目。它的目标是帮助你无缝的集成Realm到你的响应式流程。

Auto-updating results 343

数据库查询定义了一个对象的集合。在最基本的层面上,RxRealm封装结果为一个observable,将其与初始内容一起触发,然后每次集合更改时再次发生:

let realm = try! Realm()
let result = realm.objects(MyObject.self)
Observable.collection(from: result)
  .subscribe(onNext: { items in
    print("Query returned \(items.count) items")
  })
  .addDisposableTo(disposeBag)

每次你提交一个改变到数据库,它将影响结果,集合将再一次触发

Arrays 344

获得一个数组替代Realm集合是简单的:

let result = realm.objects(MyObject.self)
Observable.array(from: result)
  .subscribe(onNext: { array in
    print("Query returned \(array.count) items")
  })
  .addDisposableTo(disposeBag)
Note:因为来至结果的每个对象必须从数据库加载,有一个记忆和时间惩罚来抓取所有的对象作为一个数组。与collection(from:)工作通常是你最需的。

Asynchronous first item 344

Observable.collection(from:) and Observable.array(from:)会同步发射初始项目的集合或数组。在这时你订阅到observable( subscribe(:)函数返回前),你接收了第一个元素。这会干扰你的应用,尤其是当启动用户界面时。一个常见的错误来源是,假设下面的代码已经被执行了 - 但是没有为第一个元素写 subscribe(_:)。

幸运的是,两个函数实际上接收第二个参数,它默认是true。实际的签名是 Observable.collection(from:synchronousStart:) and Observable.array(from:synchronousStart:)。

如果你想让第一个元素异步发射,为异步标志位传递false:

let result = realm.objects(MyObject.self)
Observable.array(from: result, synchronousStart: false)
  .subscribe(onNext: { array in
    print("Query returned \(array.count) items")
  })
  .addDisposableTo(disposeBag)

当初始Realm通知触发时,你将接收初始内容。

变更集(Changesets) 345

RxRealm能够访问更多复杂的observables。你能够获得changesets(当结果更新时Realm通知)使用 Observable.changeset(from:synchronizedStart:)。这个observable同原结果的集合一起发送changeset

let result = realm.objects(MyObject.self)
Observable.changeset(from: result)
  .subscribe(onNext: { results, changes in
  if let changes = changes {
      // it's an update
      print("deleted: \(changes.deleted)")
      print("inserted: \(changes.inserted)")
      print("updated: \(changes.updated)")
    } else {
      // it's the initial data
    print(results)
    }
  }
  .addDisposableTo(disposeBag)

Observable.arrayWithChangeset(from:synchronizedStart:)是这个API的一个变体,它返回一个数组的observable和一个Realm ChangeSet。

Single objects 345

RxRealm的最终特性让你观察单个对象并在数据库中它每次更新就获得一个新的。例如,如果你在数据库中的对象里存储用户设置,在你代码中变化的位置观察它来自动更新设置变化。

如果你正在使用Realm移动平台,为来自其他设备的活动更新尤为简单:

let hideCompletedObs = Observable.from(object: preferencesObject)
  .map { prefs -> Bool in prefs.hideCompletedTodos }
  .distinctUntilChanged()
let todosObs = realm.objects(Todo.self)
Observable.combineLatest(hideCompletedObs, todosObs) {
  hideCompleted, todos in
  if hideCompleted {
    return todos.filter { $0.completed == false }
  }
  return todos
  }
  .bindTo(tableView.rx.items) {
    (tableView: UITableView, index: Int, element: Todo) in
    // return cell here
  }
  .addDisposableTo(disposeBag)

在这种情况下,您的应用程序将显示一个待办事项列表,该列表最初会刷新一次,然后再次在用户首选项中“hide completed todos”标志更改。

如果(in case)您只对对象的特定属性的变化感兴趣,则可以使用Observable .propertyChanges(object:)来订阅每个属性的改变事件。在上面的todo应用场景中,你可能想观察一个给定任务的标题的改变,如下示:

Observable.propertyChanges(object: task)
  .filter { $0.name == "taskTitle" }
  .subscribe(onNext: { change in
    print("property \(change.name) changed from: \(change.oldValue) to: \
      (change.newValue)")
  })
  .addDisposableTo(bag)

Adding objects 346

RxRealm用 add() and delete() 观察者扩展了Realm类。你能够使用它们来观察项目增或删的序列。每次序列发射一个对象,它能够自动地从数据库增加或删除。

考虑这个情景,你需要在特定间隔为新消息查询远端服务器。当API返回新消息,你希望看到消息增加到数据库(你在你应用的某处使用RxRealm来自动更新数据库更改的消息列表):

Observable
  .timer(0, period: 60, scheduler: MainScheduler.instance)
  .flatMap { _ -> Observable<[Message]> in
    let messages = realm.objects(Messages.self).sorted(byProperty:
      "dateReceived")
    if let lastMessage = messages.last {
      return MailAPI.newMessagesSince(lastMessage.dateReceived)
    }
    return MailAPI.newMessagesSince(Date.distantPast)
  }
  .subscribe(realm.rx.add())
  .addDisposableTo(disposeBag)

简单地忽略由定时器发射的值,请求自最后接收消息的日期之后的所有信息并传递结果到RxRealm。

当你在一个realm对象上使用add()是要小心。RxRealm为订阅的持续保持了Realm数据库对象。如果你不希望订阅保持Realm对象,你可以使用它自己的变化版: Realm.rx.add() or Realm.rx.add(configuration:)——这个静态方法将抓取在当前线程的任何存在的Realm实体,并且不需要保持的使用它。

Deleting objects 347

类似的端点(endpoint)让你删除来自数据库的存在的对象或对象的集合:

let realm = try! Realm()
deleteSelectedMessagesButton.rx.tap
  .map { self.selectedMessages() }
  .bindTo(realm.rx.delete())
  .addDisposableTo(disposeBag)

再次,在订阅的整个持续时间内保持了Realm对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容