पाठ 22 / 25

A First Look at SwiftUI

Understand how Swift language features appear in a small SwiftUI view.

Where the language meets the UI

SwiftUI is Apple's declarative UI framework. A view is a struct conforming to View with a computed body property returning some View (an opaque type), built with result builders inside containers such as VStack, HStack and List. State lives in property wrappers and observation: @State for simple local values, @Binding to share them with child views, and @Observable model classes (from the Observation framework) for app state, usually annotated @MainActor. Views are values that SwiftUI recreates cheaply; when state changes, SwiftUI recomputes body and updates only what changed on screen. Asynchronous loading uses the .task modifier, which is cancelled automatically when the view disappears. Previews with #Preview (a macro) render views live in Xcode. This course covers the language; SwiftUI layout, navigation and data flow deserve their own course, but every concept you have learned (structs, closures, generics, protocols, property wrappers, concurrency) appears in even the smallest SwiftUI screen.

State drives the view

When state changes, SwiftUI recomputes the view description and updates the screen.

A small state box with an arrow into a view template, which outputs a phone screen; a loop arrow returns from the screen to the state box.
Figure 8.1 — The SwiftUI state and render loop.

A small SwiftUI screen

Structs, opaque types, property wrappers, closures and async loading together.

import SwiftUI

@MainActor
@Observable
final class ProductListModel {
    var products: [Product] = []
    var isLoading = false

    func load() async {
        isLoading = true
        defer { isLoading = false }
        products = (try? await ProductAPI.fetchAll()) ?? []
    }
}

struct ProductListView: View {
    @State private var model = ProductListModel()
    @State private var searchText = ""

    private var filtered: [Product] {
        searchText.isEmpty ? model.products
                           : model.products.filter { $0.title.localizedCaseInsensitiveContains(searchText) }
    }

    var body: some View {
        NavigationStack {
            List(filtered) { product in
                VStack(alignment: .leading) {
                    Text(product.title).font(.headline)
                    Text(product.price, format: .currency(code: "INR"))
                }
            }
            .overlay { if model.isLoading { ProgressView() } }
            .searchable(text: $searchText)
            .navigationTitle("Products")
            .task { await model.load() }              // cancelled if the view disappears
        }
    }
}

#Preview { ProductListView() }

Keep logic out of body

body may be called often. Keep it a cheap description of the UI, and put loading, validation and business rules in model types that you can unit test without SwiftUI.

त्वरित जाँच: In SwiftUI, what does `var body: some View` use?

  • An existential any View
  • A class hierarchy
  • An opaque return type: one specific view type hidden from callers
  • A property wrapper
Answer

An opaque return type: one specific view type hidden from callers — some View lets the compiler know the exact type while keeping it hidden and efficient.