SwiftUI is Apple’s modern declarative UI framework for building user interfaces across all Apple platforms. This comprehensive guide covers everything you need to know about building apps with SwiftUI.
What is SwiftUI?
SwiftUI is Apple’s declarative framework for building user interfaces on Apple platforms.
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, SwiftUI!")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Key Features
- Declarative - Describe your UI declaratively
-
- Reactive - Built on Combine framework
-
- Cross-platform - iOS, macOS, tvOS, watchOS
-
- Preview - Live previews in Xcode
-
- Animation - Powerful animation system
-
- Accessibility - Built-in accessibility support
Basic Views
Text and Images
import SwiftUI
struct BasicViews: View {
var body: some View {
VStack(spacing: 20) {
// Text
Text("Hello, World!")
.font(.title)
.fontWeight(.bold)
.foregroundColor(.blue)
// Image
Image(systemName: "star.fill")
.font(.system(size: 50))
.foregroundColor(.yellow)
// Local image
Image("myImage")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 200, height: 200)
}
}
}
Buttons
struct ButtonExamples: View {
@State private var isPressed = false
var body: some View {
VStack(spacing: 20) {
// Basic button
Button("Tap Me") {
print("Button tapped!")
}
// Button with action
Button(action: {
isPressed.toggle()
}) {
Text(isPressed ? "Pressed!" : "Press Me")
.foregroundColor(.white)
.padding()
.background(isPressed ? Color.green : Color.blue)
.cornerRadius(10)
}
// Label button
Button(action: {}) {
Label("Add Item", systemImage: "plus.circle")
}
// Link button
Button(action: {
// Open URL
}) {
Text("Learn More")
.underline()
}
}
}
}
State Management
@State
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack(spacing: 20) {
Text("\(count)")
.font(.largeTitle)
.fontWeight(.bold)
HStack(spacing: 20) {
Button("Decrease") {
if count > 0 {
count -= 1
}
}
Button("Increase") {
count += 1
}
}
.buttonStyle(.borderedProminent)
}
}
}
@Binding
struct ParentView: View {
@State private var name = "John"
var body: some View {
ChildView(name: $name)
}
}
struct ChildView: View {
@Binding var name: String
var body: some View {
TextField("Enter name", text: $name)
.textFieldStyle(.roundedBorder)
}
}
@Observable (iOS 17+)
@Observable
class CounterModel {
var count = 0
func increment() {
count += 1
}
}
struct CounterView: View {
let model = CounterModel()
var body: some View {
VStack {
Text("\(model.count)")
.font(.largeTitle)
Button("Increment") {
model.increment()
}
}
}
}
@ObservedObject
class UserViewModel: ObservableObject {
@Published var users: [User] = []
func loadUsers() {
// Load users...
}
}
struct UserListView: View {
@ObservedObject var viewModel: UserViewModel
var body: some View {
List(viewModel.users) { user in
Text(user.name)
}
}
}
Layout Views
VStack, HStack, ZStack
struct LayoutExamples: View {
var body: some View {
// Vertical stack
VStack(alignment: .leading, spacing: 10) {
Text("Title")
Text("Subtitle")
}
// Horizontal stack
HStack(spacing: 15) {
Image(systemName: "star")
Text("Rating: 5")
}
// ZStack (overlay)
ZStack {
Color.blue
.frame(width: 100, height: 100)
Text("Overlay")
.foregroundColor(.white)
}
}
}
List and ScrollView
struct ListExample: View {
let items = ["Apple", "Banana", "Cherry", "Date"]
var body: some View {
List {
ForEach(items, id: \.self) { item in
Text(item)
}
}
.listStyle(.insetGrouped)
}
}
struct ScrollViewExample: View {
var body: some View {
ScrollView {
VStack(spacing: 20) {
ForEach(1...10, id: \.self) { index in
Text("Item \(index)")
.padding()
.background(Color.gray.opacity(0.2))
}
}
}
}
}
LazyVStack/LazyHStack
struct LazyListExample: View {
var body: some View {
ScrollView {
LazyVStack(spacing: 10) {
ForEach(1...100, id: \.self) { index in
Text("Item \(index)")
.frame(height: 50)
.frame(maxWidth: .infinity)
.background(Color.gray.opacity(0.1))
}
}
}
}
}
Navigation
NavigationStack
struct NavigationExample: View {
var body: some View {
NavigationStack {
List {
NavigationLink("User Details", destination: UserDetailView())
NavigationLink("Settings", destination: SettingsView())
}
.navigationTitle("Home")
}
}
}
struct UserDetailView: View {
var body: some View {
Text("User Details")
.navigationTitle("User")
}
}
TabView
struct TabViewExample: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
HomeView()
.tabItem {
Label("Home", systemImage: "house")
}
.tag(0)
SearchView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
.tag(1)
ProfileView()
.tabItem {
Label("Profile", systemImage: "person")
}
.tag(2)
}
}
}
Forms
TextField and SecureField
struct FormExample: View {
@State private var email = ""
@State private var password = ""
@State private var rememberMe = false
var body: some View {
Form {
Section {
TextField("Email", text: $email)
.textContentType(.emailAddress)
.autocapitalization(.none)
SecureField("Password", text: $password)
.textContentType(.password)
}
Section {
Toggle("Remember me", isOn: $rememberMe)
Button("Login") {
// Login action
}
.frame(maxWidth: .infinity)
}
}
}
}
Modifiers
Common Modifiers
struct ModifiersExample: View {
var body: some View {
Text("Styled Text")
.font(.title)
.fontWeight(.bold)
.foregroundColor(.white)
.padding()
.background(Color.blue)
.cornerRadius(10)
.shadow(color: .gray, radius: 5, x: 2, y: 2)
.padding()
}
}
Conditional Modifiers
struct ConditionalModifier: View {
@State private var isHighlighted = false
var body: some View {
Text("Conditional")
.padding()
.background(
RoundedRectangle(cornerRadius: 8)
.fill(isHighlighted ? Color.blue : Color.gray)
)
.onTapGesture {
isHighlighted.toggle()
}
}
}
Animations
Implicit Animations
struct AnimatedView: View {
@State private var isExpanded = false
var body: some View {
VStack {
Button("Toggle") {
withAnimation {
isExpanded.toggle()
}
}
Rectangle()
.fill(Color.blue)
.frame(
width: isExpanded ? 200 : 100,
height: isExpanded ? 200 : 100
)
.animation(.easeInOut(duration: 0.3), value: isExpanded)
}
}
}
Explicit Animations
struct ExplicitAnimation: View {
@State private var degrees: Double = 0
var body: some View {
Button("Rotate") {
withAnimation(.spring(response: 0.5, dampingFraction: 0.6)) {
degrees += 360
}
}
Image(systemName: "star.fill")
.font(.system(size: 50))
.rotationEffect(.degrees(degrees))
}
}
Networking
URLSession with Async/Await
struct User: Identifiable, Codable {
let id: Int
let name: String
let email: String
}
struct UserListView: View {
@State private var users: [User] = []
@State private var isLoading = false
var body: some View {
Group {
if isLoading {
ProgressView()
} else {
List(users) { user in
VStack(alignment: .leading) {
Text(user.name)
.font(.headline)
Text(user.email)
.font(.subheadline)
.foregroundColor(.gray)
}
}
}
}
.task {
await loadUsers()
}
}
func loadUsers() async {
isLoading = true
defer { isLoading = false }
guard let url = URL(string: "https://api.example.com/users") else { return }
do {
let (data, _) = try await URLSession.shared.data(from: url)
users = try JSONDecoder().decode([User].self, from: data)
} catch {
print("Error: \(error)")
}
}
}
Data Flow
Environment
struct ChildView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
Text("Color scheme: \(colorScheme == .dark ? "Dark" : "Light")")
}
}
EnvironmentObject
class AppState: ObservableObject {
@Published var isLoggedIn = false
}
struct ContentView: View {
@StateObject private var appState = AppState()
var body: some View {
Text("Hello")
.environmentObject(appState)
}
}
struct DetailView: View {
@EnvironmentObject var appState: AppState
}
SwiftUI for macOS
Window Management
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.windowStyle(.hiddenTitleBar)
.commands {
CommandGroup(replacing: .newItem) {
Button("New Document") {
// Create new document
}
}
}
}
}
External Resources
Conclusion
SwiftUI provides a powerful and intuitive way to build user interfaces across Apple platforms. Key points:
- Declarative syntax simplifies UI code
- Built-in state management with @State, @Binding, @ObservedObject
- Powerful navigation with NavigationStack and TabView
- Native animations and transitions
- Works alongside UIKit when needed
For Apple platform development, SwiftUI is the recommended modern approach to building UIs.
Comments