Sie haben es nicht in Ihre Frage aufgenommen, aber ich denke, der Fehler, den Sie erhalten, wenn Sie ohne den Stapel auskommen, ist der folgende?
Die Funktion deklariert einen undurchsichtigen Rückgabetyp, hat jedoch keine Rückgabeanweisungen in ihrem Hauptteil, aus denen auf einen zugrunde liegenden Typ geschlossen werden kann
Der Fehler gibt Ihnen einen guten Hinweis darauf, was vor sich geht, aber um ihn zu verstehen, müssen Sie das Konzept der undurchsichtigen Rückgabetypen verstehen . So rufen Sie die Typen auf, denen das some
Schlüsselwort vorangestellt ist . Ich habe auf der WWDC keine Apple-Ingenieure gesehen, die sich eingehend mit diesem Thema befasst haben (vielleicht habe ich den jeweiligen Vortrag verpasst?). Deshalb habe ich selbst viel recherchiert und einen Artikel darüber geschrieben, wie diese Typen funktionieren und warum sie verwendet werden Rückgabetypen in SwiftUI .
Es gibt auch eine ausführliche technische Erklärung in einer anderen
Wenn Sie vollständig verstehen möchten, was los ist, empfehle ich, beide zu lesen.
Als kurze Erklärung hier:
Allgemeine Regel:
Funktionen oder Eigenschaften mit einem undurchsichtigen Ergebnistyp ( some Type
)
müssen immer denselben konkreten Typ zurückgeben .
In Ihrem Beispiel gibt Ihre body
Eigenschaft je nach Bedingung einen anderen Typ zurück:
var body: some View {
if someConditionIsTrue {
TabView()
} else {
LoginView()
}
}
Wenn someConditionIsTrue
, würde es a zurückgeben TabView
, sonst a LoginView
. Dies verstößt gegen die Regel, weshalb sich der Compiler beschwert.
Wenn Sie Ihre Bedingung in eine Stapelansicht einschließen, enthält die Stapelansicht die konkreten Typen beider bedingter Zweige in einem eigenen generischen Typ:
HStack<ConditionalContent<TabView, LoginView>>
Unabhängig davon, welche Ansicht tatsächlich zurückgegeben wird, ist der Ergebnistyp des Stapels immer derselbe, und daher beschwert sich der Compiler nicht.
💡 Ergänzend:
Es gibt tatsächlich eine Ansichtskomponente, die SwiftUI speziell für diesen Anwendungsfall bereitstellt, und genau diese wird von Stacks intern verwendet, wie Sie im obigen Beispiel sehen können:
Es hat den folgenden generischen Typ, wobei der generische Platzhalter automatisch aus Ihrer Implementierung abgeleitet wird:
ConditionalContent<TrueContent, FalseContent>
Ich empfehle, diesen Ansichtscontainer anstelle eines Stapels zu verwenden, da er anderen Entwicklern seinen Zweck semantisch klar macht.