A view in SwiftUI is a lightweight, transient object designed to be thrown away when the source for it is changed.
Unlike views in UIKit, SwiftUI views are not intended to be permanent or manually updated and instead of recomputed dynamically whenever the underlying data changes.
Views in SwiftUI are all struct
, which means they are value types.
These views have advantages:
struct
are lightweight and performant- Views are immutable making them predictable and easy to reason about
All SwiftUI views conform to the View
protocol which requires a single computed body property that describes the view's content.
Here is a minimal example of a SwiftUI view:
struct MyView: View {
var body: some View {
Text("Hello, SwiftUI!")
.padding()
}
}
Note that the view is composed of another view ( Text("Hello, SwiftUI!") is another view)
SwiftUI views use a data-driven paradigm meaning that the views are driven by the data that backs them.
Ultimately this simplifies the UI updates significantly as it isn't necessary to manually refresh, reload or redraw views. The process is simpler since once the data is updated SwiftUI takes care of the view updates.
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
.font(.largeTitle)
Button("Increment") {
count += 1
}
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
SwiftUI provides us .onAppear()
and .onDisappear()
modifiers.
.onAppear()
This instance method adds an action to perform before the view appears. Therefore we can think of this as roughly analogous to UIKit's viewWillAppear
function.
.onDisappear()
This instance method adds an action to perform after the view disappears. Therefore we can think of this as roughly analogous to UIKit's viewDidDisappear
function.
Modifiers and lifecycle methods
Modifiers can also be used to hook into the view lifecycle. For instance, the .onAppear()
and .onDisappear()
modifiers allow you to execute code when a view appears or disappears, respectively.
Text("Hello, World!")
.onAppear {
print("The view has appeared")
}
.onDisappear {
print("The view has disappeared")
}
So in this code onAppear
and onDisappear
are both modifiers.
Article: https://stevenpcurtis.medium.com/the-swiftui-view-lifecycle-c3630ca2b833
SwiftUI offers tools to manage state, ensuring views stay in sync with the data that drives them.
@State
For local, mutable state within a view.
@Binding
For passing state between views.
@Environment
and @EnvironmentObject For managing shared app-wide data.
Article: https://medium.com/@stevenpcurtis/swiftuis-state-management-f6422c5731e9
If we create a simple screen to represent a user profile that is split into three components, ProfileImageView
, ProfileNameView
, and ProfileBioView
, which is then combined in a ProfileView
.
import SwiftUI
struct ProfileView: View {
var body: some View {
VStack(spacing: 20) {
ProfileImageView(imageName: "profile_image")
ProfileNameView(name: "John Doe")
ProfileBioView(bio: "iOS Developer passionate about creating innovative solutions.")
}
.padding()
}
}
struct ProfileImageView: View {
var imageName: String
var body: some View {
Image(imageName)
.resizable()
.scaledToFit()
.frame(width: 100, height: 100)
.clipShape(Circle())
.shadow(radius: 5)
}
}
struct ProfileNameView: View {
var name: String
var body: some View {
Text(name)
.font(.title)
.fontWeight(.bold)
}
}
struct ProfileBioView: View {
var bio: String
var body: some View {
Text(bio)
.font(.body)
.foregroundColor(.gray)
.multilineTextAlignment(.center)
}
}
Each component is responsible for one specific part of the UI, and ProfileView
simply combines them. This approach makes the code modular and easy to manage.
Article: https://medium.com/@stevenpcurtis/view-composition-in-swiftui-9386625b243c
Think in Terms of Data Flow Focus on how data flows through your app rather than manually managing views.
Decompose Complex UIs Break down large views into smaller, reusable components for better maintainability.
SwiftUI views represent a modern, efficient, and intuitive way to build user interfaces. Their transient, data-driven nature allows developers to focus on what their app should display rather than how to update it. By embracing SwiftUI's declarative approach, you can write more concise, readable, and maintainable code while letting the framework handle the complexities of view management.