Наличие VStack как свойства в Struct - PullRequest
0 голосов
/ 21 февраля 2020

Мне нужно иметь VStack в качестве свойства в структуре, подобной этой

struct Str
{ 
  let view: VStack
  ....
}

Компилятор говорит:
"Ссылка на тип * VS VS * generic требует аргументов в < ...>
Insert '<< # Content: View # >>'
"

Xcodes" fix "выдает:

struct Str
{
  let view: VStack<Content: View>
  ...
}

Но компилятор по-прежнему жалуется:
"Ожидается '>' для завершения обобщенного c списка аргументов"

Разрешено ли иметь VStack в структуре?

1 Ответ

2 голосов
/ 21 февраля 2020

Вы обнаружили, что 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. по-разному в ответ, а затем переход может оживить

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...