Operator之元素映射(Mapping elements)
之前讲解过map
, compactmap
, flatmap
操作符的区别,本篇主要讲解scan
,tryScan
,map
,tryMap
和flatMap
,并对元素映射类进行归纳。
scan
计算学生总成绩:
let scores = [1,2,3]
func calculateTotalScore(_ scores: [Int]) -> Int {
var totalScore: Int = 0
for score in scores {
totalScore += score
}
return totalScore
}
使用响应式编程scan
进行改造:
let scores = [1,2,3]
_ = scores
.publisher
.scan(0) { acc, current -> Int in
acc + current
}
.sink(receiveValue: { someValue in
print(someValue)
})
scan
适用于需要数据累积的场景,scan
能记忆一个单位的数据。它能够把上次计算后的结果保存起来,以便在下次计算的时候,获取到这个值。
tryScan
tryScan
在scan
的基础之上,让我们能够在闭包中主动抛出异常。
_ = ["a", "b", "c"]
.publisher
.tryScan("") { acc, current -> String in
if current == "c" {
throw TryScanError.customError
}
return acc + current
}
.sink(receiveCompletion: { _ in
print("结束了")
}, receiveValue: { someValue in
print(someValue)
})
map/tryMap
scan
收集数据,map
和tryMap
映射数据。
使用map
转换数据:
[1, 2, 3]
.publisher
.map { int in "Number: \(int)" }
.sink(receiveValue: { int in
print(int)
})
输出:
Number: 1
Number: 2
Number: 3
同tryScan
一样,tryMap
允许闭包中抛出异常
enum MyFailure: Error {
case negative
}
[1, -2, 3]
.publisher
.tryMap { intValue -> Int in
if intValue < 1 {
throw MyFailure.negative
}
return intValue
}
flatMap
flatMap
把上游输出的值转换为一个新的pulisher,典型应用场景如解析json
字符串:
Just(json)
.flatMap { data in
return Just(data)
.decode(YourType.self, JSONDecoder())
.catch {
return Just(YourType.placeholder)
}
}