你应该知道的5个Swift组合变换操作符

想随时随地轻松变更数据格式?本文将教你5种解法!我将在Xcode Playground中创建示例函数
首页 新闻资讯 行业资讯 你应该知道的5个Swift组合变换操作符

本文转载自公众号“读芯术”(ID:AI_Discovery)。

想随时随地轻松变更数据格式?本文将教你5种解法!我将在Xcode Playground中创建示例函数,运行它们并观察结果。

[[334295]]

1. map

.map 操作符允许我们转换闭包中来自发布者的所有元素。

复制

var subscriptions =Set<AnyCancellable>()                                             funcmapExample() {                           let subject =PassthroughSubject<Int, Never>()                           subject                               .map { (integer) in                                   returnString(integer)                           }                           .sink(receiveValue: {                               print("Value: \($0), Type: \(type(of: $0))")                           })                           .store(in: &subscriptions)                           subject.send(12)                           subject.send(31)                           subject.send(55)                           subject.send(4)                           subject.send(18)                       }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

下面是这段代码的作用:

  • 创建一个接受Int 值的PassthroughSubject。

  • 使用.map 操作符将每个接收到的Int 值转换为String。

  • 然后,订阅发布者并打印转换后的元素的值和类型。

向受试者发送随机数以观察以下结果:

你应该知道的5个Swift组合变换操作符

还有一种巧妙的方法来使用对象的键路径获取对象的属性:

复制

funcmapKeyPathExample() {                         structCarBrand {                             let title:String                             let country:String                         }                                let carBrandsSubject =PassthroughSubject<CarBrand, Never>()                           carBrandsSubject                             .map(\.country)                             .sink(receiveValue: { country in                                 print("Country:\(country)")                             })                             .store(in: &subscriptions)                                carBrandsSubject.send(                             CarBrand(title: "MercedesBenz", country: "Germany")                         )                                carBrandsSubject.send(                             CarBrand(title: "Ford", country: "USA")                         )                                carBrandsSubject.send(                             CarBrand(title: "Honda", country: "Japan")                         )                     }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

使用.map(\.country),可以访问CarBrand的国家属性。然后只需打印每个国家:

你应该知道的5个Swift组合变换操作符

2. replaceNil

顾名思义,.replaceNil 操作符将每个接收到的nil元素转换为指定的元素:

复制

funcreplaceNilExample() {                         let values: [Int?] = [123, nil, nil, 12, 10]                         let valuesvaluesPublisher =values.publisher                                valuesPublisher                             .replaceNil(with: 0)                             .map { $0! }                             .collect()                             .sink(receiveValue: { print($0) })                             .store(in: &subscriptions)                     }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

请注意,还可以将多个操作符组合在一起以达到必要的结果。首先将每个nil 值替换为0,然后强制解开值,最后将所有值收集在一个数组中:

你应该知道的5个Swift组合变换操作符

需要注意的是在.map  操作符中使用强制展开的方法。如果你不喜欢强行解包该怎么办?我们还有一个.map协变量:.compactMap,它能自动转发仅非零的那些元素:

复制

funcreplaceNilExample() {                         let values: [Int?] = [123, nil, nil, 12, 10]                         let valuesvaluesPublisher = values.publisher                                valuesPublisher                             .replaceNil(with: 0)                             .compactMap { $0 }                             .collect()                             .sink(receiveValue: { print($0) })                             .store(in: &subscriptions)     }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

3. collect

使用.collect操作符可以很容易地收集所有接收到的元素,并发出一个包含所有元素的数组:

复制

funccollectExample() {                      let integers = [1, 4, 5, 12, 24, 44]                            let integerPublisher =integers.publisher                            integerPublisher                          .collect()                          .sink(receiveValue: { print($0) })                          .store(in: &subscriptions)                  }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

于是我们得到了想要的结果:

你应该知道的5个Swift组合变换操作符

注意,发布者必须发出.completed事件才能实现这个操作,因为.collect会一直等待,直到所有元素都发出并且发布者完成操作为止。例如,如果使用PassthroughSubject,需要在发送所有元素后发送.finished事件:

复制

funccollectExample() {                      let integerPublisher =PassthroughSubject<Int, Never>()                            integerPublisher                          .collect()                          .sink(receiveValue: { print($0) })                          .store(in: &subscriptions)                            integerPublisher.send(1)                      integerPublisher.send(4)                      integerPublisher.send(5)                      integerPublisher.send(12)                      integerPublisher.send(24)                      integerPublisher.send(44)                            integerPublisher.send(completion: .finished)                  }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

4. flatMap

.flatMap操作符允许我们将给定的发布者转换为另一个发布者。来看看它是如何将观察结果从Network更改为isAvailable主题:

复制

funccollectExample() {                      let integerPublisher =PassthroughSubject<Int, Never>()                            integerPublisher                          .collect()                          .sink(receiveValue: { print($0) })                          .store(in: &subscriptions)                            integerPublisher.send(1)                      integerPublisher.send(4)                      integerPublisher.send(5)                      integerPublisher.send(12)                      integerPublisher.send(24)                      integerPublisher.send(44)                            integerPublisher.send(completion: .finished)                  }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

当更改它的值时,我们要打印出isAvailable值。首先,它打印初始值(正在使用CurrentValueSubject),一旦为其分配了新值,就会发生以下情况:

你应该知道的5个Swift组合变换操作符

5. scan

.scan操作符能够在闭包中公开当前发出的值以及最新的值。可以使用它来累积值并打印总结果:

复制

funcflatMapExample() {                      structNetwork {                          let title:String                          let isAvailable =CurrentValueSubject<Bool, Never>(false)                      }                            let wifi =Network(title: "Wi-Fi")                            let networkSubject = CurrentValueSubject<Network, Never>(wifi)                            networkSubject                          .flatMap ({                              return$0.isAvailable                          })                          .sink(receiveValue: {                              print("Is networkenabled: \($0)")                          })                          .store(in: &subscriptions)                            wifi.isAvailable.value=true                            wifi.isAvailable.value=false                  }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

在这里,执行的是以下操作:

  • 创建收益数组(下划线是将数字中的千单位分开的好方法)。

  • 创建这些收益的发布者。

  • 使用.scan操作符,将当前发出的值($0)添加到从零开始的最新值($1)。

最后,计算出总收益:

你应该知道的5个Swift组合变换操作符

【责任编辑:赵宁宁 TEL:(010)68476606】

 

37    2020-07-20 15:15:06    Swift 函数 代码