为什么在这种情况下需要类型擦除



我有一个简单的协议Provider,如下所示:

protocol Provider {
func get() -> String
}

和一个以存在Provider为字段的结构体S

struct S {
var provider: any Provider
}

我还有一个视图ProviderView,如下所示:

struct ProviderView<P: Provider>: View {
let provider: P

var body: some View {
Text(provider.get())
}
}

以及类似Provider的实现:

struct DummyProvider: Provider {
func get() -> String {
"Hello World!"
}
}

现在,当我尝试在S.provider:中使用ProviderView传递时,问题来了

struct ContentView: View {
let s = S(provider: DummyProvider())

var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)

ProviderView(provider: s.provider) // This is the erroring line.
}
}
}

出现错误:

Type 'any Provider' cannot conform to 'Provider'

现在,这是意料之中的事,正如在这里和这里的回答中出色地描述的那样。

此代码不起作用的原因是Viewbody属性在运行时是固定的,因此不允许ProviderView动态类型上是泛型的。

问题是,一个超薄型擦除AnyProvider结构修复了这个问题:

struct AnyProvider: Provider {
let erased: any Provider

func get() -> String {
return erased.get()
}
}

现在ProviderView有一个具体的类型要泛型。

但是,您可以看到AnyProvider本身实际上只是存储一个any Provider成员变量。AnyProvider的大小应该仍然未知。

我认为,如果问题是any Provider的大小在运行时未知,那么为什么使用AnyProvider可以解决这个问题呢?毕竟,它只包含一个在运行时大小未知的字段。

所以我的问题是:为什么Swift不能合成一个类似的包装器使用any Provider和包含单个类型为any Provider的字段的结构有什么区别

是什么阻止Swift允许您使用any ProviderAnyProvider

除了类型之外,AnyProvider如何比any Provider更具体

我真的很想知道我是否错过了什么。

附言:我用的是Xcode 14 Beta 3和Swift 5.7。

尝试用any Provider声明您的ProviderView

struct ProviderView: View {
let provider: any Provider

var body: some View {
Text(provider.get())
}
}