Вы не включили его в свой вопрос, но я полагаю, ошибка, которую вы получаете при работе без стека, следующая?
Функция объявляет непрозрачный тип возвращаемого значения, но не имеет в своем теле операторов возврата, из которых можно вывести базовый тип
Ошибка дает вам хороший намек на то, что происходит, но чтобы понять это, вам необходимо понять концепцию непрозрачных типов возврата . Вот как вы называете типы с префиксом some
. Я не видел, чтобы инженеры Apple углублялись в эту тему на WWDC (может быть, я пропустил соответствующий доклад?), Поэтому я сам провел много исследований и написал статью о том, как эти типы работают и почему они используются как типы возврата в SwiftUI .
Существует также подробное техническое объяснение в другом
Если вы хотите полностью понять, что происходит, я рекомендую прочитать оба.
В качестве быстрого объяснения здесь:
Общее правило:
Функции или свойства с непрозрачным типом результата (some Type
)
всегда должен возвращать тот же конкретный тип .
В вашем примере ваше свойство body
возвращает другой тип , в зависимости от условия:
var body: some View {
if someConditionIsTrue {
TabView()
} else {
LoginView()
}
}
Если someConditionIsTrue
, он вернет TabView
, иначе LoginView
. Это нарушает правило, поэтому компилятор жалуется.
Если вы заключите свое условие в представление стека, представление стека будет включать конкретные типы обеих условных веток в свой собственный универсальный тип:
HStack<ConditionalContent<TabView, LoginView>>
Как следствие, независимо от того, какое представление фактически возвращено, тип результата стека всегда будет одинаковым, и, следовательно, компилятор не будет жаловаться.
? Дополнительно:
На самом деле есть компонент вида SwiftUI предоставляет специально для этого варианта использования, и это фактически то, что стеки используют внутри, как вы можете видеть в примере выше:
Он имеет следующий универсальный тип, а универсальный заполнитель автоматически выводится из вашей реализации:
ConditionalContent<TrueContent, FalseContent>
Я рекомендую использовать этот контейнер представления, а не стек, потому что он делает его назначение семантически понятным для других разработчиков.