我只是在学习如何使用合并。我有使用Rx(RxSwift和RxJava)的经验,我注意到它们非常相似。
但是,Publisher
协议没有为其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)
}
4条答案
按热度按时间vuktfyat1#
更新
未来就是现在!如果您使用Xcode14.0测试版2或更高版本,您可以像这样编写
createPublisher
函数,并且应该将其重新部署到所有支持Combine的系统:此外,您可以使用不透明的参数类型使函数采用语法较少的泛型
Publisher
参数,而无需求助于存在词或AnyPublisher
:原创
截至撰写本文时,SWIFT还没有您想要的功能。Joe Groff在他的“Improving the UI of generics” document的标题为“函数返回缺少类型级抽象”一节中特别描述了缺失的内容:
然而,想要从调用方抽象出实现选择的返回类型**是很常见的。例如,一个函数可能会生成一个集合,但不想透露它到底是哪种集合的详细信息。这可能是因为实现者希望保留在将来的版本中更改集合类型的权利,或者因为实现使用组合的
lazy
转换并且不想在其接口中公开长的、脆弱的、令人困惑的返回类型。首先,在这种情况下,人们可能会尝试使用存在词:但斯威夫特今天会告诉你,
Collection
只能用作通用约束,这会让人自然而然地尝试这样做:但这也不起作用,因为如上所述,
Output
泛型参数是由调用方选择的-该函数签名声称能够返回调用方要求的任何类集合,而不是实现使用的一种特定类型的集合。有可能有一天,不透明的返回类型语法(
some Publisher
)将被扩展以支持这种使用。今天你有三个选择。为了理解它们,让我们考虑一个具体的例子。假设您想要从URL获取一个整数文本列表,每行一个,并将每个整数作为单独的输出发布:
选项一:拼写返回类型
您可以使用完整、复杂的返回类型。它看起来是这样的:
我自己也没弄清楚退货类型。我将返回类型设置为
Int
,然后编译器告诉我Int
不是正确的返回类型,错误消息包含正确的返回类型。这不是很好,如果您更改实现,则必须确定新的返回类型。选项二:使用
AnyPublisher
将
.eraseToAnyPublisher()
添加到发布服务器的末尾:这是常见且简单的解决方案,通常也是您想要的。如果您不喜欢拼写
eraseToAnyPublisher
,您可以编写自己的Publisher
扩展名来使用更短的名称,如下所示:选项三:编写自己的
Publisher
类型您可以用自己的类型 Package 您的出版商。您的类型的
receive(subscriber:)
构造“真正的”发布服务器,然后将订阅服务器传递给它,如下所示:rkkpypqq2#
使用不透明返回时,类型是由闭包返回的内容定义的,因此您可以只使用
而且它起作用了。使用Xcode11.4进行了测试。
mtb9vblg3#
我在
some Publisher
(恼人的限制)上运气不佳。一种选择是使用
AnyPublisher
:或者,“Apple Way”(他们在标准库中使用的)似乎是类型别名(或 Package 器结构):
这就是组合框架中
Publishers
命名空间的用途。结构比类型别名更不透明。类型别名可能会导致像
Cannot convert Utils.MyTypeAlias (aka 'TheLongUnderlyingTypeOf') to expected type ABC
这样的错误消息,因此您最接近正确的不透明类型可能是使用结构,这实际上就是AnyPublisher
。vxf3dgd44#
一个非常简单的技巧帮助我们减少了大部分冗长,基本上是创建一个包含以下内容的文件: