首页 iOS.& Swift Books RXSWIFT:SWIFT的无功

9
结合运营商 由佛罗特州撰写

In earlier chapters, you learned how to create, filter and transform observable sequences. RxSwift filtering and transformation operators behave much like Swift’s standard collection operators. You got a glimpse into the true power of RxSwift with flatMap, the workhorse operator that lets you perform a lot of tasks with very little code.

本章将向您介绍几种不同的方式来组装序列,以及如何将每个序列中的数据结合起来。你会工作的一些运营商都非常相似,雨燕集合运营商。他们帮助组合来自异步序列的元素,就像你用斯威夫特阵列做。

入门

对于本章,您将使用与基本构建块设置的Xcode Playground,您需要通过章节任务。

要开始使用,打开MacOS的终端应用程序(在你的Mac的发现 应用程序> Utilities 文件夹),导航到当前章节的启动项目文件夹,然后运行像这样的引导脚本:

$ ./bootstrap.sh

You will again use the example(of:) construct to wrap your code in distinct blocks. Remember to show the Debug Area in Xcode (under the 看法调试区域 menus), as this is where playground print(_:) statements display their output.

rxsword没有关于使用和掌握异步序列的。但是你需要在混乱中进行命令!通过组合可观察可实现很多。

前缀和连接

与观测工作时,首先最明显的需要是保证观察者接收到的初始值。在有些情况下,你需要的“当前状态”第一次的情况。良好的用例这是“当前位置”和“网络连接状态”。这些都是你要与当前状态前缀一些观测。

example(of: "startWith") {
  // 1
  let numbers = Observable.of(2, 3, 4)
  
  // 2
  let observable = numbers.startWith(1)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
——— Example of: startWith ———
1
2
3
4

example(of: "Observable.concat") {
  // 1
  let first = Observable.of(1, 2, 3)
  let second = Observable.of(4, 5, 6)
  
  // 2
  let observable = Observable.concat([first, second])
  
  observable.subscribe(onNext: { value in
    print(value)
  })
}
example(of: "concat") {
  let germanCities = Observable.of("Berlin", "Münich", "Frankfurt")
  let spanishCities = Observable.of("Madrid", "Barcelona", "Valencia")
  
  let observable = germanCities.concat(spanishCities)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
example(of: "concatMap") {
  // 1
  let sequences = [
    "German cities": Observable.of("Berlin", "Münich", "Frankfurt"),
    "Spanish cities": Observable.of("Madrid", "Barcelona", "Valencia")
  ]

  // 2
  let observable = Observable.of("German cities", "Spanish cities")
    .concatMap { country in sequences[country] ?? .empty() }

  // 3
  _ = observable.subscribe(onNext: { string in
      print(string)
    })
}

合并

RxSwift提供了几种序列结合。最简单的地方入手 merge。你能想象它从下面的图表呢?

example(of: "merge") {
  // 1
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
  // 2
  let source = Observable.of(left.asObservable(), right.asObservable())
  // 3
  let observable = source.merge()
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  // 4
  var leftValues = ["Berlin", "Munich", "Frankfurt"]
  var rightValues = ["Madrid", "Barcelona", "Valencia"]
  repeat {
      switch Bool.random() {
      case true where !leftValues.isEmpty:
          left.onNext("Left:  " + leftValues.removeFirst())
      case false where !rightValues.isEmpty:
          right.onNext("Right: " + rightValues.removeFirst())
      default:
          break
      }
  } while !leftValues.isEmpty || !rightValues.isEmpty
  // 5
  left.onCompleted()
  right.onCompleted()
}
——— Example of: merge ———
Right: Madrid
Left:  Berlin
Right: Barcelona
Right: Valencia
Left:  Munich
Left:  Frankfürt

结合元素

在RxSwift运营商的一个重要组是 combineLatest 家庭。他们从几个序列合并值:

example(of: "combineLatest") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
  // 1
  let observable = Observable.combineLatest(left, right) {
    lastLeft, lastRight in
    "\(lastLeft) \(lastRight)"
  }

  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  // 2
  print("> Sending a value to Left")
  left.onNext("Hello,")
  print("> Sending a value to Right")
  right.onNext("world")
  print("> Sending another value to Right")
  right.onNext("RxSwift")
  print("> Sending another value to Left")
  left.onNext("Have a good day,")
  left.onCompleted()
  right.onCompleted()
}
let observable = Observable
  .combineLatest(left, right) { ($0, $1) }
  .filter { !$0.0.isEmpty }
example(of: "combine user choice and value") {
  let choice: Observable<DateFormatter.Style> = Observable.of(.short, .long)
  let dates = Observable.of(Date())
  
  let observable = Observable.combineLatest(choice, dates) {
    format, when -> String in
    let formatter = DateFormatter()
    formatter.dateStyle = format
    return formatter.string(from: when)
  }
  
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
  // 1
  let observable = Observable.combineLatest([left, right]) {
    strings in strings.joined(separator: " ")
  }

example(of: "zip") {
  enum Weather {
    case cloudy
    case sunny
  }
  let left: Observable<Weather> = Observable.of(.sunny, .cloudy, .cloudy, .sunny)
  let right = Observable.of("Lisbon", "Copenhagen", "London", "Madrid", "Vienna")
  let observable = Observable.zip(left, right) { weather, city in
    return "It's \(weather) in \(city)"
  }
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
——— Example of: zip ———
It's sunny in Lisbon
It's cloudy in Copenhagen
It's cloudy in London
It's sunny in Madrid

触发

应用有不同的需求,必须管理多个输入源。你会经常需要在每盎司从几个观测接受输入。有些人会简单地触发代码中的操作,而其他人将提供数据。 RxSwift了强大的运营商,这将使您的生活更轻松覆盖。那么,你的 编码 life at least!

example(of: "withLatestFrom") {
  // 1
  let button = PublishSubject<Void>()
  let textField = PublishSubject<String>()
  
  // 2
  let observable = button.withLatestFrom(textField)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  
  // 3
  textField.onNext("Par")
  textField.onNext("Pari")
  textField.onNext("Paris")
  button.onNext(())
  button.onNext(())
}
Paris
Paris

  // 2
  let observable = textField.sample(button)

开关

RxSwift comes with two main so-called “switching” operators: amb(_:)switchLatest(). They both allow you to produce an observable sequence by switching between the events of the combined or source sequences. This allows you to decide which sequence’s events will the subscriber receive at runtime.

example(of: "amb") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
  
  // 1
  let observable = left.amb(right)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  
  // 2
  left.onNext("Lisbon")
  right.onNext("Copenhagen")
  left.onNext("London")
  left.onNext("Madrid")
  right.onNext("Vienna")
  
  left.onCompleted()
  right.onCompleted()
}

example(of: "switchLatest") {
  // 1
  let one = PublishSubject<String>()
  let two = PublishSubject<String>()
  let three = PublishSubject<String>()
  
  let source = PublishSubject<Observable<String>>()
  // 2
  let observable = source.switchLatest()
  let disposable = observable.subscribe(onNext: { value in
    print(value)
  })
  // 3
  source.onNext(one)
  one.onNext("Some text from sequence one")
  two.onNext("Some text from sequence two")
  
  source.onNext(two)
  two.onNext("更多的 text from sequence two")
  one.onNext("和 also from sequence one")
  
  source.onNext(three)
  two.onNext("Why don't you see me?")
  one.onNext("I'm alone, help me")
  three.onNext("Hey it's three. I win.")
  
  source.onNext(one)
  one.onNext("Nope. It's me, one!")
  disposable.dispose()
}
——— Example of: switchLatest ———
Some text from sequence one
More text from sequence two
Hey it's three. I win.
Nope. It's me, one!

将元素组合在序列中

所有的厨师都知道你的减少越多,就会越大。虽然不是厨师,但莱克斯特必须将酱汁减少到它的美味组件。

example(of: "reduce") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  // 1
  let observable = source.reduce(0, accumulator: +)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
  // 1
  let observable = source.reduce(0) { summary, newValue in
    return summary + newValue
  }

example(of: "scan") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  let observable = source.scan(0, accumulator: +)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
——— Example of: scan ———
1
4
9
16
25

挑战

您在本章中了解了很多关于许多运营商的许多。但是更多地有更多的学习(更有趣的是有趣)关于序列组合!

挑战:ZIP案例

You’ve learned about the zip family of operators that lets you go through sequences in lockstep — it’s time to start using it.

有技术问题吗?要报告bug? 你可以问的问题和bug报告本书的作者在我们的官书论坛 这里.

有关于网上阅读体验反馈给份额? 如果您有关于UI,UX,突出显示或我们在线阅读器的其他功能的反馈,您可以将其发送到设计团队,其中表格如下所示:

© 2021 Razeware LLC

您正在阅读的自由,以显示为本章的部分 混淆了 文本。解锁这本书,以及我们整个书籍和视频目录,带有Raywenderlich.com的专业订阅。

现在解锁

为了突出或做笔记,你需要通过自己拥有这本书的订阅或能力。