如何获得 iOS 13 的 SubscribeOn flatMap 运算符?
How to get SubscribeOn flatMap operator for iOS 13?
此代码无法在 iOS 13 上编译,因为 flatMap 仅在 iOS 中可用 14. 如何扩展 SubscribeOn 以获得 flatMap 运算符?
func f1(_ value: Int) -> Future<Int, Error> {
Future { promise in
print("\(Thread.current): f1() value = \(value)")
promise(.success(value + 1))
}
}
func f2(_ value: Int) -> Future<Int, Error> {
Future { promise in
print("\(Thread.current): f2() value = \(value)")
promise(.success(value + 1))
}
}
let a1 = Just(0)
.subscribe(on: DispatchQueue.global())
.flatMap(f1)
.flatMap(f2)
.receive(on: DispatchQueue.main)
.sink { _ in
print("\(Thread.current): completed")
} receiveValue: { value in
print("\(Thread.current): sink() value = \(value)")
}
更新
这是我的解决方案现在的样子:
extension Publishers.SubscribeOn {
func myFlatMap<P>(_ transform: @escaping (Self.Output) -> P) -> Publishers.FlatMap<P, Publishers.SetFailureType<Self, P.Failure>> where P: Publisher {
Publishers.FlatMap<P, Publishers.SetFailureType<Self, P.Failure>>(
upstream: Publishers.SetFailureType<Self, P.Failure>(upstream: self),
maxPublishers: .unlimited,
transform: transform
)
}
}
aflatMap
运算符在iOS13中可用,但还有moreflatMap
运算符在 iOS 14.
中可用
具体来说,the only flatMap
operator available in iOS 13要求上游发布者(在你的例子中,Just<Int>
)和内部发布者(在你的例子中,Future<Int, Error>
)具有相同的Failure
类型。但是 Just<Int>.Failure
是 Never
,而 Future<Int, Error>.Failure
是 Error
。
在iOS14中,额外重载了三个flatMap
,用于三种情况的特殊处理:
- when the upstream
Failure
type is Never
,
- when the inner
Failure
type is Never
,
- 和when both the upstream
Failure
and the inner Failure
are Never
.
您的示例代码属于第一种特殊情况(上游 Failure
是 Never
),因此它针对 iOS 14 进行编译,但不针对 iOS 13 进行编译。
您可以通过使用 setFailureType
运算符显式转换 Just
来解决此问题:
let a1 = Just(0)
.setFailureType(to: Error.self)
.subscribe(on: DispatchQueue.global())
.flatMap(f1)
.flatMap(f2)
.receive(on: DispatchQueue.main)
.sink { _ in
print("\(Thread.current): completed")
} receiveValue: { value in
print("\(Thread.current): sink() value = \(value)")
}
或者,您可以使用 Result.Publisher
从必要的 Failure
类型开始 Error
。 Swift 甚至应该可以为你推导出来:
let a1 = Result.success(0).publisher
.subscribe(on: DispatchQueue.global())
.flatMap(f1)
.flatMap(f2)
.receive(on: DispatchQueue.main)
.sink { _ in
print("\(Thread.current): completed")
} receiveValue: { value in
print("\(Thread.current): sink() value = \(value)")
}
此代码无法在 iOS 13 上编译,因为 flatMap 仅在 iOS 中可用 14. 如何扩展 SubscribeOn 以获得 flatMap 运算符?
func f1(_ value: Int) -> Future<Int, Error> {
Future { promise in
print("\(Thread.current): f1() value = \(value)")
promise(.success(value + 1))
}
}
func f2(_ value: Int) -> Future<Int, Error> {
Future { promise in
print("\(Thread.current): f2() value = \(value)")
promise(.success(value + 1))
}
}
let a1 = Just(0)
.subscribe(on: DispatchQueue.global())
.flatMap(f1)
.flatMap(f2)
.receive(on: DispatchQueue.main)
.sink { _ in
print("\(Thread.current): completed")
} receiveValue: { value in
print("\(Thread.current): sink() value = \(value)")
}
更新 这是我的解决方案现在的样子:
extension Publishers.SubscribeOn {
func myFlatMap<P>(_ transform: @escaping (Self.Output) -> P) -> Publishers.FlatMap<P, Publishers.SetFailureType<Self, P.Failure>> where P: Publisher {
Publishers.FlatMap<P, Publishers.SetFailureType<Self, P.Failure>>(
upstream: Publishers.SetFailureType<Self, P.Failure>(upstream: self),
maxPublishers: .unlimited,
transform: transform
)
}
}
aflatMap
运算符在iOS13中可用,但还有moreflatMap
运算符在 iOS 14.
具体来说,the only flatMap
operator available in iOS 13要求上游发布者(在你的例子中,Just<Int>
)和内部发布者(在你的例子中,Future<Int, Error>
)具有相同的Failure
类型。但是 Just<Int>.Failure
是 Never
,而 Future<Int, Error>.Failure
是 Error
。
在iOS14中,额外重载了三个flatMap
,用于三种情况的特殊处理:
- when the upstream
Failure
type isNever
, - when the inner
Failure
type isNever
, - 和when both the upstream
Failure
and the innerFailure
areNever
.
您的示例代码属于第一种特殊情况(上游 Failure
是 Never
),因此它针对 iOS 14 进行编译,但不针对 iOS 13 进行编译。
您可以通过使用 setFailureType
运算符显式转换 Just
来解决此问题:
let a1 = Just(0)
.setFailureType(to: Error.self)
.subscribe(on: DispatchQueue.global())
.flatMap(f1)
.flatMap(f2)
.receive(on: DispatchQueue.main)
.sink { _ in
print("\(Thread.current): completed")
} receiveValue: { value in
print("\(Thread.current): sink() value = \(value)")
}
或者,您可以使用 Result.Publisher
从必要的 Failure
类型开始 Error
。 Swift 甚至应该可以为你推导出来:
let a1 = Result.success(0).publisher
.subscribe(on: DispatchQueue.global())
.flatMap(f1)
.flatMap(f2)
.receive(on: DispatchQueue.main)
.sink { _ in
print("\(Thread.current): completed")
} receiveValue: { value in
print("\(Thread.current): sink() value = \(value)")
}