Skip to main content
โšก Calmops

SwiftUI: Apple's Modern UI Framework

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))
                }
            }
        }
    }
}
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