Вы обнаружили, что VStack
на самом деле не тип. Мы можем более точно описать его как «конструктор типов». Он объявлен так:
struct VStack<Content> where Content : View {
...
}
В качестве аргумента Content
вы указываете какой-то другой тип, а он дает вам тип. Вы даете ему тип Text
и получаете обратно тип VStack<Text>
. Вы даете ему тип Image
и получаете обратно тип VStack<Image>
. Типы, которые вы получаете, разные типы! Объект типа VStack<Text>
- это , а не объект типа VStack<Image>
.
Так что вам просто нужно знать, какой тип передать в качестве аргумента, верно? Проблема в том, что лотов «типов» SwiftUI на самом деле являются обобщенными c конструкторами типов. Таким образом, тип становится сложным. Вот пример из приложения, над которым я работаю:
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>
на ErrorView
).
Так как вы решите это? Одним из способов является использование AnyView
:
struct Str {
let view: AnyView
...
}
let str = Str(view: AnyView(VStack {
...
}))
Обратите внимание, что иногда вы услышите совет, которого следует избегать AnyView
. Вот Джо Грофф , объясняющий почему:
Вы можете использовать оболочку AnyView для явного обертывания типов, где они могут динамически изменяться.
Однако система анимации будет Вам будет легче, если вы сможете сделать это как можно дальше вниз по графу представления. Вы можете иметь один тип макета, который принимает .portrait
/ .landscape
, применять вращение, перевод и т. Д. c. по-разному в ответ, а затем переход может оживить