In SwiftUI, creating an app usually involves more than just a single view, such as a basic “Hello World” app. To add multiple views, you need to use stacks. There are three types of stacks in SwiftUI: HStack, VStack, and ZStack.
The Hello World app initially looks like this:
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello World")
}
}
If you try to add a second Text view directly within the ContentView struct, like this:
struct ContentView: View {
var body: some View {
Text("Hello World")
Text("Hello again!")
}
}
It won’t work as expected. To add multiple views, you need to enclose them within a stack.
Let’s try using VStack:
struct ContentView: View {
var body: some View {
VStack {
Text("Hello World")
Text("Hello again!")
}
}
}
Now, the views are aligned vertically, one after the other.
HStack, on the other hand, aligns views horizontally:
struct ContentView: View {
var body: some View {
HStack {
Text("Hello World")
Text("Hello again!")
}
}
}
And ZStack places views on top of each other, which can sometimes create overlapping:
struct ContentView: View {
var body: some View {
ZStack {
Text("Hello World")
Text("Hello again!")
}
}
}
ZStack is particularly useful for scenarios like placing a background image with text overlaid on top.
In SwiftUI, we organize our UI using these three stacks - HStack, VStack, and ZStack. Additionally, we have another view called Group, which allows us to group together multiple views without affecting the layout.
VStack {
Group {
Text("Hello World")
Text("Hello again!")
}
}
Groups can come in handy when applying modifiers to child views or when a view can only have a maximum of 10 children. By grouping views, you can combine up to 10 views into a single group.
Both stack views and Group are views themselves, so they can also have modifiers applied to them. Modifiers can affect the view they are applied to or be used to apply the same property to multiple views simultaneously.
For example, applying a modifier directly to a Text view:
Text("Hello World")
.font(.largeTitle)
Or applying a modifier to a VStack:
VStack {
Text("Hello World")
Text("Hello again!")
}
.font(.largeTitle)
In the second example, the font modifier was applied to the VStack, resulting in both Text views having the .largeTitle font.
This approach is particularly useful for environment modifiers, which are a specific type of modifier. Note that not all modifiers can be used this way, but environment modifiers, such as the font modifier, can be applied to container views to affect multiple child views simultaneously.