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

pinkon5k  于 2022-11-28  发布在  Swift
关注(0)|答案(1)|浏览(137)

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

protocol Provider {
    func get() -> String
}

还有一个结构体S,它有一个存在的Provider作为字段:

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!"
    }
}

现在,当我尝试使用ProviderView传入S.provider时,问题出现了:

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'

现在这是预期的,正如在回答herehere中出色地描述的。
这段代码不起作用的原因是因为Viewbody属性在运行时是固定的,因此不允许ProviderViewdynamic类型是泛型。
问题是,一个超薄类型的擦除AnyProvider结构体修复了这个问题:

struct AnyProvider: Provider {
    let erased: any Provider
    
    func get() -> String {
        return erased.get()
    }
}

现在ProviderView有一个具体的类型可以泛型化。
但是,您可以看到AnyProvider本身实际上只存储了一个any Provider成员变量,AnyProvider的大小应该仍然未知。
我认为如果问题是any Provider的大小在运行时是未知的,那么为什么使用AnyProvider来解决这个问题呢?毕竟,它只包含一个在运行时大小未知的字段。
所以我的问题是:为什么Swift不能合成一个类似的 Package 器?使用any Provider和包含any Provider类型的单个字段的结构体有什么区别?
是什么阻止Swift允许您使用any ProviderAnyProvider

AnyProviderany Provider除了类型以外,还有什么更具体的地方?

我真的很想知道我是否遗漏了什么。
我正在使用Xcode 14 Beta 3和Swift 5.7。

xzlaal3s

xzlaal3s1#

尝试使用any Provider声明ProviderView

struct ProviderView: View {
    let provider: any Provider
    
    var body: some View {
        Text(provider.get())
    }
}

相关问题