我很好奇AnyView
SwiftUI 中的默认实现。如何将具有不同泛型类型的结构放入协议数组中?
例如:
let a = AnyView(Text("hello"))
let b = AnyView(Image(systemName: "1.circle"))
let genericViews = [a, b] // No compile error
Run Code Online (Sandbox Code Playgroud)
而我的实现:
struct TypeErasedView<V: View>: View {
private var _view: V
init(_ view: V) {
_view = view
}
var body: V {
_view
}
}
let a = TypeErasedView(Text("Hello"))
let b = TypeErasedView(Image(systemName: "1.circle"))
let genericViews = [a, b] // compile error
Run Code Online (Sandbox Code Playgroud)
编译错误将是“异构集合文字只能被推断为 '[Any]';如果这是有意的,请添加显式类型注释”。
有没有人有任何想法?
这是可能方法的演示。它经过简化,但显示了如何完成此操作的一般想法......或者至少是一个方向。
完整的可编译和工作模块。在 Xcode 11.2 / iOS 13.2 上测试
import SwiftUI
private protocol TypeErasing {
var view: Any { get }
}
private struct TypeEraser<V: View>: TypeErasing {
let orinal: V
var view: Any {
return self.orinal
}
}
public struct MyAnyView : View {
public var body: Never {
get {
fatalError("Unsupported - don't call this")
}
}
private var eraser: TypeErasing
public init<V>(_ view: V) where V : View {
eraser = TypeEraser(orinal: view)
}
fileprivate var wrappedView: Any { // << they might have here something specific
eraser.view
}
public typealias Body = Never
}
struct DemoAnyView: View {
let container: [MyAnyView]
init() {
let a = MyAnyView(Text("Hello"))
let b = MyAnyView(Image(systemName: "1.circle"))
container = [a, b]
}
var body: some View {
VStack {
// dynamically restoring types is different question and might be
// dependent on Apple's internal implementation, but here is
// just a demo that it works
container[0].wrappedView as! Text
container[1].wrappedView as! Image
}
}
}
struct DemoAnyView_Previews: PreviewProvider {
static var previews: some View {
DemoAnyView()
}
}
Run Code Online (Sandbox Code Playgroud)
这是因为你有一个通用的限制。AnyView
没有通用约束。您使用底层泛型实例化它View
,但它Body
始终声明为Never
. 这里可能会发生编译器魔法,因为我无法让通用的无约束版本工作。
归档时间: |
|
查看次数: |
1564 次 |
最近记录: |