Swift 5.7存在的问题
我最近转换了一些最初使用Type-Erasure的代码,以使用新的Swift 5.7 任何
存在。 但是,在尝试使用使用已实现的通用类型的任何
关键字时,我会遇到一些问题。
我在 Xcode 14 beta 2 上运行此操作(已隐式打开了存在)。
这是一个示例:
protocol Provider<Value> {
associatedtype Value
func get() -> Value
}
struct S {
var stringProvider: any Provider<String>
}
这是一个非常简单的struct s
,它具有成员StringProvider
。我在这里使用任何
关键字,而不是制作任何提供商&lt; string&gt;
generic,因为我希望能够重新分配string> strignprovider
后来(有不同类型)。
struct ProviderView<P: Provider>: View {
let provider: P
var body: some View {
Text(String(describing: type(of: provider.get())))
}
}
现在,我有一个providerView
swiftui struct,它可以使用提供者
并与之一起做事。
struct DummyProvider: Provider {
typealias Value = String
func get() -> String {
"Hello World!"
}
}
这只是一个虚拟提供商
实现,它只是返回字符串。
这一切都很好,当我尝试使用providerview
的情况下,问题就出现了。
struct ContentView: View {
let s = S(stringProvider: DummyProvider())
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
ProviderView(provider: s.stringProvider) // This is the erroring line
}
}
}
我遇到一个错误,说键入'任何提供商&lt; string&gt;'不能符合“提供者”
。
我想我知道为什么,这是因为providerview
不能将任何
存在作为通用参数。
我的问题是:是否有任何办法,而无需返回键入擦除?我做的事情真的很错吗?请记住,我需要能够将其他类型的s.stringprovider
重新分配。
I recently converted some of my code which originally used Type-Erasure to use the new Swift 5.7 any
existential.
However, I'm getting some issues when trying to use the any
keyword with already implemented generic types.
I'm running this on Xcode 14 Beta 2 (which has Implicitly Opened Existentials).
Here is an example:
protocol Provider<Value> {
associatedtype Value
func get() -> Value
}
struct S {
var stringProvider: any Provider<String>
}
Here is a very simple struct S
which has a member stringProvider
. I use the any
keyword here instead of making any Provider<String>
generic because I would like to be able to reassign stringProvider
to a different value later on (which has a different type).
struct ProviderView<P: Provider>: View {
let provider: P
var body: some View {
Text(String(describing: type(of: provider.get())))
}
}
Now here I have a ProviderView
SwiftUI struct, which takes in a Provider
and does stuff with it.
struct DummyProvider: Provider {
typealias Value = String
func get() -> String {
"Hello World!"
}
}
And this is just a dummy Provider
implementation which just returns a string.
This all works fine, the problem comes when I try to use ProviderView
with an existential any
.
struct ContentView: View {
let s = S(stringProvider: DummyProvider())
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
ProviderView(provider: s.stringProvider) // This is the erroring line
}
}
}
I get an error saying Type 'any Provider<String>' cannot conform to 'Provider'
.
I think I know why, it's because ProviderView
cannot have an any
existential as a generic argument.
My question is: Is there any way around this, without going back to type erasure? Am I doing something really badly wrong? Keep in mind that I need to be able to reassign S.stringProvider
to a Provider
of a different type.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里的问题在于
body
需要是某种特定类型,因此ProviderView需要是某种特定类型(因为Body
依赖于该类型)。它在运行时无法更改。因此,如果在运行时会更改,ProviderView不能对其提供商进行通用。这意味着
providerView.provider
需要为任何提供商
而不是通用:因此,该部分是可以预期的。
您会遇到的问题是当前的运行时尚无法完全处理,稍后您会出现错误:
我希望以后的Beta在Beta中有所改善,尽管我鼓励您打开跟踪它的反馈。
The problem here is that
body
needs to be some specific type, so ProviderView needs to be some specific type (sincebody
relies on that type). It can't change at runtime. So ProviderView can't be generic over its Provider if that's going to change at runtime.That means that
ProviderView.provider
needs to beany Provider
, not generic:So that part is expected.
The problem you'll run into is that the current runtime can't quite handle this yet, and you'll get an error later:
I do expect this to improve in later betas, though I encourage you to open a Feedback to track it.
任何提供商
都是存在的,并且存在性是某种框,不符合框内的协议,因此您会看到错误。如果您不想拥有
providerView
generic,则可以添加使用某些
- 这表示符合协议的实际值,因此编译器很高兴。尽管有了这样的通用视图,但使用
提供商
,您无法完成很多工作。any Provider
is an existential, and existentials being some kind of boxes, don't conform to the protocol inside the box, thus you see the error.If you're not keen on having
ProviderView
generic, you can add a custom initializer that usessome
- this represents the actual value conforming to the protocol, so the compiler is happy.Though with a generic view like this, there's not much you can accomplish with the
provider
.