Day 16 – Passing Data Between Views in SwiftUI
T
Tuan Beo

Day 16 – Passing Data Between Views in SwiftUI

Master sending data from one view to another in SwiftUI using initializers, @Binding, and environment objects.

1️⃣ Passing Data with Initializers (One-Way)

The simplest way — pass values into a view via parameters.
This is read-only in the child view.

struct GreetingView: View {
    var name: String
    var body: some View {
        Text("Hello, \(name)!")
    }
}

GreetingView(name: "Vy") // Passed down

2️⃣ Two-Way Binding with @Binding

If you want the child view to change the parent’s data, use @Binding.

struct CounterView: View {
    @Binding var count: Int
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
            Button("Increase") { count += 1 }
        }
    }
}

Parent View:

@State private var number = 0
CounterView(count: $number) // `$` creates a binding

3️⃣ Using @ObservedObject & @StateObject

For shared data across multiple views, we use ObservableObject.

class FriendListViewModel: ObservableObject {
    @Published var friends: [Friend] = []
}

4️⃣ Updating Our Friend App

We’ll make FriendDetailView able to update a friend’s online status.

import SwiftUI

struct Friend: Identifiable, Hashable {
    let id = UUID()
    var name: String
    var isOnline: Bool
}

class FriendsViewModel: ObservableObject {
    @Published var friends: [Friend] = [
        .init(name: "Anna", isOnline: true),
        .init(name: "Tom", isOnline: false),
        .init(name: "Vy", isOnline: true)
    ]
}

struct ContentView: View {
    @StateObject private var viewModel = FriendsViewModel()
    
    var body: some View {
        NavigationStack {
            List {
                ForEach($viewModel.friends) { $friend in
                    NavigationLink(destination: FriendDetailView(friend: $friend)) {
                        HStack {
                            Circle()
                                .frame(width: 10, height: 10)
                                .foregroundStyle(friend.isOnline ? .green : .gray)
                            Text(friend.name)
                        }
                    }
                }
            }
            .navigationTitle("Friends")
        }
    }
}

struct FriendDetailView: View {
    @Binding var friend: Friend
    
    var body: some View {
        Form {
            Text(friend.name)
                .font(.title)
            Toggle("Online", isOn: $friend.isOnline)
        }
        .navigationTitle("Edit Friend")
        .navigationBarTitleDisplayMode(.inline)
    }
}

#Preview {
    ContentView()
}

How This Works

  • FriendsViewModel → Central data model storing the list.

  • @StateObject in ContentView → Owns the data.

  • @Binding in FriendDetailView → Allows editing the specific friend directly.

  • Changes in FriendDetailView instantly update the List in ContentView.


🛠 Practice

  1. Add an "Edit Name" TextField in FriendDetailView to rename a friend.

  2. Add a "Mark All Offline" button in ContentView that sets all isOnline to false.

  3. Try creating another screen that shows only online friends by filtering the list.

Comments