最近,我将一些最初使用Type的代码转换为使用新的SWIFT5.7 any存在权。但是,当尝试在已经实现的泛型类型中使用any关键字时,我会遇到一些问题。
我在Xcode 14 Beta 2上运行这个程序(它已经隐式地打开了Existential)。
下面是一个示例:
protocol Provider<Value> {
associatedtype Value
func get() -> Value
}
struct S {
var stringProvider: any Provider<String>
}下面是一个非常简单的结构S,它有一个成员stringProvider。我在这里使用any关键字,而不是使any Provider<String>泛化,因为我希望以后能够将stringProvider重新分配到不同的值(该值具有不同的类型)。
struct ProviderView<P: Provider>: View {
let provider: P
var body: some View {
Text(String(describing: type(of: provider.get())))
}
}现在我有了一个ProviderView SwiftUI结构,它接收一个Provider并使用它进行操作。
struct DummyProvider: Provider {
typealias Value = String
func get() -> String {
"Hello World!"
}
}这只是一个虚拟的Provider实现,它只返回一个字符串。
这一切都很好,当我尝试将ProviderView与存在主义的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
}
}
}我说Type 'any Provider<String>' cannot conform to 'Provider'时出错了。
我想我知道为什么,这是因为ProviderView不能将any存在主义作为一个通用的论点。
我的问题是:有什么办法可以绕过这个问题,而不返回类型擦除?我做错什么了吗?请记住,我需要能够将S.stringProvider重新分配到不同类型的Provider。
发布于 2022-07-04 21:42:32
这里的问题是body需要某种特定类型,所以ProviderView需要某种特定类型(因为body依赖于该类型)。它不能在运行时改变。因此,如果要在运行时改变ProviderView,那么它就不能对其提供程序具有通用性。
这意味着ProviderView.provider需要是any Provider,而不是泛型的:
struct ProviderView: View {
let provider: any Provider
var body: some View {
Text(String(describing: type(of: provider.get())))
}
}所以这部分是应该的。
您将遇到的问题是当前运行时还不能完全处理这一问题。,稍后您将得到一个错误:
// Runtime support for parameterized protocol types is only available in iOS 99.0.0 or newer
ProviderView(provider: s.stringProvider)虽然我鼓励你打开一个反馈来跟踪它,但我确实希望这在以后的贝塔中得到改进。
发布于 2022-07-05 04:55:28
any Provider是一种存在主义,而存在物是某种类型的盒子,不符合盒子内的协议,因此你会看到错误。
如果您不热衷于拥有ProviderView泛型,您可以添加一个使用some的自定义初始化器--这表示符合协议的实际值,因此编译器很高兴。
struct ProviderView: View {
let provider: any Provider
init(provider: some Provider) {
self.provider = provider
}
var body: some View {
Text(String(describing: type(of: provider.get())))
}
}虽然有了这样一个通用视图,但是使用provider没有什么可以完成的。
https://stackoverflow.com/questions/72861825
复制相似问题