- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我只是在学习如何使用Combine。我有使用 Rx(RxSwift 和 RxJava)的经验,我注意到它非常相似。
然而,完全不同的一件事(而且有点烦人)是 Publisher
协议(protocol)不为其 Output
使用泛型和 Failure
类型;它改为使用关联类型。
这意味着我不能指定多态 Publisher
类型(例如 Publisher<Int, Error>
)并简单地返回符合 Publisher
的任何类型与那些类型。我需要使用 AnyPublisher<Int, Error>
相反,我被迫包含eraseToAnyPublisher()
到处都是。
如果这是唯一的选择,那我就忍了。但是,我最近也了解了 Swift 中的不透明类型,我想知道是否可以使用它们来解决这个问题。
有没有办法让我拥有一个返回 some Publisher
的函数?并为 Output
使用特定类型和 Failure
?
这似乎是不透明类型的完美案例,但我不知道是否有办法既使用不透明类型又指定关联类型。
我正在描绘这样的事情:
func createPublisher() -> some Publisher where Output = Int, Failure = Error {
return Just(1)
}
最佳答案
在撰写本文时,Swift 没有您想要的功能。 Joe Groff 在他的 “Improving the UI of generics” document 中标题为“函数返回缺少类型级抽象”的部分中具体描述了缺少的内容。 :
However, it's common to want to abstract a return type chosen by theimplementation from the caller. For instance, a function may producea collection, but not want to reveal the details of exactly what kindof collection it is. This may be because the implementer wants toreserve the right to change the collection type in future versions, orbecause the implementation uses composed
lazy
transforms and doesn'twant to expose a long, brittle, confusing return type in itsinterface. At first, one might try to use an existential in thissituation:func evenValues<C: Collection>(in collection: C) -> Collection where C.Element == Int {
return collection.lazy.filter { $0 % 2 == 0 }
}but Swift will tell you today that
Collection
can only be used as ageneric constraint, leading someone to naturally try this instead:func evenValues<C: Collection, Output: Collection>(in collection: C) -> Output
where C.Element == Int, Output.Element == Int
{
return collection.lazy.filter { $0 % 2 == 0 }
}but this doesn't work either, because as noted above, the
Output
generic argument is chosen by the caller—this function signature isclaiming to be able to return any kind of collection the caller asksfor, instead of one specific kind of collection used by theimplementation.
some Publisher
)有可能有一天会被扩展以支持这种使用。
return dataTaskPublisher(for: url)
.mapError { $0 as Error }
.flatMap { data, response in
(response as? HTTPURLResponse)?.statusCode == 200
? Result.success(data).publisher
: Result.failure(URLError(.resourceUnavailable)).publisher
}
.compactMap { String(data: $0, encoding: .utf8) }
.map { data in
data
.split(separator: "\n")
.compactMap { Int($0) }
}
.flatMap { $0.publisher.mapError { $0 as Error } }
选项 1:说明返回类型
extension URLSession {
func ints(from url: URL) -> Publishers.FlatMap<
Publishers.MapError<
Publishers.Sequence<[Int], Never>,
Error
>,
Publishers.CompactMap<
Publishers.FlatMap<
Result<Data, Error>.Publisher,
Publishers.MapError<
URLSession.DataTaskPublisher,
Error
>
>,
[Int]
>
> {
return dataTaskPublisher(for: url)
... blah blah blah ...
.flatMap { $0.publisher.mapError { $0 as Error } }
}
}
我自己没有弄清楚返回类型。我将返回类型设置为
Int
然后编译器告诉我
Int
不是正确的返回类型,并且错误消息包含正确的返回类型。这并不漂亮,如果您更改实现,您将不得不找出新的返回类型。
AnyPublisher
添加
.eraseToAnyPublisher()
到出版商的末尾:
extension URLSession {
func ints(from url: URL) -> AnyPublisher<Int, Error> {
return dataTaskPublisher(for: url)
... blah blah blah ...
.flatMap { $0.publisher.mapError { $0 as Error } }
.eraseToAnyPublisher()
}
}
这是常见且简单的解决方案,通常也是您想要的。如果您不喜欢拼写
eraseToAnyPublisher
,你可以自己写
Publisher
扩展名以使用较短的名称执行此操作,如下所示:
extension Publisher {
var typeErased: AnyPublisher<Output, Failure> { eraseToAnyPublisher() }
}
选项 3:编写自己的
Publisher
类型
receive(subscriber:)
构造“真正的”发布者,然后将订阅者传递给它,如下所示:
extension URLSession {
func ints(from url: URL) -> IntListPublisher {
return .init(session: self, url: url)
}
}
struct IntListPublisher: Publisher {
typealias Output = Int
typealias Failure = Error
let session: URLSession
let url: URL
func receive<S: Subscriber>(subscriber: S) where
S.Failure == Self.Failure, S.Input == Self.Output
{
session.dataTaskPublisher(for: url)
.flatMap { $0.publisher.mapError { $0 as Error } }
... blah blah blah ...
.subscribe(subscriber)
}
}
关于swift - 有没有办法避免到处使用 AnyPublisher/eraseToAnyPublisher?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61553264/
我是一名优秀的程序员,十分优秀!