swift - 将 VStack 作为 Struct 中的属性
问题描述
我需要VStack
在这样的结构中拥有一个属性
struct Str
{
let view: VStack
....
}
编译器说:
“对泛型 'VStack' 的引用需要在 <...>
Insert '<<#Content: View#>>'中使用参数
”
Xcodes“修复”产生:
struct Str
{
let view: VStack<Content: View>
...
}
但编译器仍然抱怨:
“预期 '>' 来完成通用参数列表”
是否允许在结构中包含 VStack?
解决方案
你发现那VStack
不是真正的类型。我们可以更准确地将其描述为“类型构造函数”。它是这样声明的:
struct VStack<Content> where Content : View {
...
}
你给它一些其他类型作为它的Content
参数,它给你一个类型。你给它 type Text
,然后你得到 type VStack<Text>
。你给它 type Image
,然后你得到 type VStack<Image>
。你回来的类型是不同的类型!类型的对象不是VStack<Text>
类型的对象。VStack<Image>
所以你只需要知道要传递什么类型作为参数,对吧?好吧,问题在于许多SwiftUI “类型”实际上是泛型类型构造函数。所以类型变得复杂。这是我正在开发的应用程序的示例:
var body: some View {
VStack(spacing: 0) {
scene
if store.model.latestError != nil {
Divider()
ErrorView(store: errorStore)
.padding(20)
}
} //
.frame(width: 450)
}
是什么类型的body
?我可以在运行时打印它以找出:
print(type(of: AppView(store: store).body))
输出是
ModifiedContent<VStack<TupleView<(AnyView, Optional<TupleView<(Divider, ModifiedContent<ErrorView, _PaddingLayout>)>>)>>, _FrameLayout>
请注意,返回的对象类型body
暴露了很多关于body
' 实现的细节。例如,因为ErrorView
有一个padding
修饰符,所以body
对象的类型包括ModifiedContent<ErrorView, _PaddingLayout>
. 我可以在不更改类型的情况下将填充量从 20 更改为 30。但是,如果我完全删除padding
修饰符,它会更改类型(通过更改ModifiedContent<ErrorView, _PaddingLayout>
为 just ErrorView
)。
那么你如何解决这个问题呢?一种方法是使用AnyView
:
struct Str {
let view: AnyView
...
}
let str = Str(view: AnyView(VStack {
...
}))
请注意,有时您会听到应避免的建议AnyView
。这是Joe Groff解释原因:
您可以使用 AnyView 包装器显式包装类型,它们可以动态更改。
但是,如果您可以将其尽可能向下推到视图图上,则动画系统将更容易。您可以拥有一种 Layout 类型,它采用
.portrait
/.landscape
、应用旋转、平移等以不同方式响应,然后过渡可以动画
推荐阅读
- db2 - 为什么我的查询出现“SQL0134N 字符串列使用不当...”错误?
- python - 列表差异/麻烦绘图
- java - 处理失败的 Spring Cloud Task Launcher
- java - 如何在静态上下文中等待线程?
- xpath - 如何使用 TestCafé 编写包含 ID 的 xpath?
- svelte - 如何将数据从布局传递到 Sapper 中的页面?
- spring - Spring @RolesAllowed:返回 403 或 401,但不是 500 错误
- scala - 从 DB ResultSet 填充案例类
- reactjs - React Hook useCallback 不更新状态值
- android - Pixel 2 (Android 10) 在 Android Studio 上断开连接