Bird
Raised Fist0
iOS Swiftmobile~20 mins

ObservableObject protocol in iOS Swift - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Counter Screen
A simple screen that shows a number and a button to increase it. The number updates automatically when changed using ObservableObject and @Published.
Target UI
-------------------
|   Counter App   |
-------------------
|                 |
|       0         |
|                 |
|   [ Increase ]  |
-------------------
Create a class that conforms to ObservableObject.
Add a @Published integer property to hold the count.
Build a SwiftUI view that observes this object.
Display the current count in a Text view.
Add a Button that increments the count when tapped.
Starter Code
iOS Swift
import SwiftUI

// TODO: Create ObservableObject class here

struct CounterView: View {
    // TODO: Add @StateObject or @ObservedObject property here

    var body: some View {
        VStack(spacing: 20) {
            // TODO: Display count here

            // TODO: Add button to increase count
        }
        .padding()
    }
}

struct CounterView_Previews: PreviewProvider {
    static var previews: some View {
        CounterView()
    }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
iOS Swift
import SwiftUI

class CounterModel: ObservableObject {
    @Published var count = 0
}

struct CounterView: View {
    @StateObject var model = CounterModel()

    var body: some View {
        VStack(spacing: 20) {
            Text("\(model.count)")
                .font(.largeTitle)
                .accessibilityLabel("Current count")

            Button("Increase") {
                model.count += 1
            }
            .buttonStyle(.borderedProminent)
            .accessibilityLabel("Increase count button")
        }
        .padding()
    }
}

struct CounterView_Previews: PreviewProvider {
    static var previews: some View {
        CounterView()
    }
}

We created CounterModel as a class that follows ObservableObject. It has a @Published property count that SwiftUI watches for changes.

In CounterView, we use @StateObject to create and keep the model alive. The view shows the current count in a large font.

The button calls a closure that increases count. Because count is @Published, the view updates automatically.

We added accessibility labels for better support.

Final Result
Completed Screen
-------------------
|   Counter App   |
-------------------
|                 |
|       0         |
|                 |
|   [ Increase ]  |
-------------------
Tapping the 'Increase' button adds 1 to the number shown.
The number updates immediately without needing to reload the screen.
Stretch Goal
Add a 'Reset' button that sets the count back to zero.
💡 Hint
Add another Button below the 'Increase' button that sets model.count = 0 when tapped.

Practice

(1/5)
1. What is the main purpose of the ObservableObject protocol in SwiftUI?
easy
A. To handle user input events
B. To create a new view in SwiftUI
C. To allow a class to notify views when its data changes
D. To manage app navigation between screens

Solution

  1. Step 1: Understand ObservableObject role

    The ObservableObject protocol is designed to let a class broadcast changes to its data.
  2. Step 2: Connect data changes to UI updates

    When data changes, views observing the object update automatically, keeping UI in sync.
  3. Final Answer:

    To allow a class to notify views when its data changes -> Option C
  4. Quick Check:

    ObservableObject = Notify views on data change [OK]
Hint: ObservableObject = data change notifier for views [OK]
Common Mistakes:
  • Confusing ObservableObject with view creation
  • Thinking it handles user input directly
  • Assuming it manages navigation
2. Which of the following is the correct way to mark a property inside an ObservableObject class so that changes notify the UI?
easy
A. @State var count: Int = 0
B. @Published var count: Int = 0
C. var count: Int = 0
D. @ObservedObject var count: Int = 0

Solution

  1. Step 1: Identify property wrapper for change notification

    Inside an ObservableObject, properties that should notify views must use @Published.
  2. Step 2: Check other options

    @State is for views, @ObservedObject is for view properties, and plain var does not notify.
  3. Final Answer:

    @Published var count: Int = 0 -> Option B
  4. Quick Check:

    Use @Published for ObservableObject properties [OK]
Hint: Use @Published to notify UI from ObservableObject [OK]
Common Mistakes:
  • Using @State inside ObservableObject class
  • Forgetting @Published wrapper
  • Confusing @ObservedObject with property wrapper
3. Given this code snippet, what will be printed when the button is tapped once?
class Counter: ObservableObject {
  @Published var count = 0
}

struct ContentView: View {
  @StateObject var counter = Counter()

  var body: some View {
    Button("Tap") {
      counter.count += 1
      print(counter.count)
    }
  }
}
medium
A. 1
B. Button tapped
C. 0
D. Compilation error

Solution

  1. Step 1: Understand initial value and increment

    The count starts at 0 and increments by 1 when the button is tapped.
  2. Step 2: Check print output after increment

    After increment, count is 1, so print outputs 1.
  3. Final Answer:

    1 -> Option A
  4. Quick Check:

    Increment then print = 1 [OK]
Hint: Increment before print means output is 1 [OK]
Common Mistakes:
  • Printing before increment
  • Confusing initial value with updated value
  • Assuming compilation error due to ObservableObject
4. Identify the error in this ObservableObject class that prevents UI updates:
class TimerData: ObservableObject {
  var seconds = 0

  func tick() {
    seconds += 1
  }
}
medium
A. Missing @Published on seconds property
B. Class must inherit from NSObject
C. tick() must be marked as @Published
D. ObservableObject requires struct, not class

Solution

  1. Step 1: Check property change notification

    The seconds property is not marked with @Published, so changes won't notify views.
  2. Step 2: Verify other options

    ObservableObject does not require NSObject inheritance, methods can't be @Published, and it must be a class.
  3. Final Answer:

    Missing @Published on seconds property -> Option A
  4. Quick Check:

    @Published missing = no UI update [OK]
Hint: Properties must be @Published to notify UI [OK]
Common Mistakes:
  • Thinking methods can be @Published
  • Believing ObservableObject needs NSObject
  • Confusing class and struct requirements
5. You want to create a SwiftUI view that updates automatically when a user's name changes. Which combination correctly connects the ObservableObject and the view?
class UserData: ObservableObject {
  @Published var name: String = ""
}

struct UserView: View {
  // What property wrapper and type should be used here?
  var userData: UserData

  var body: some View {
    Text(userData.name)
  }
}
hard
A. @StateObject var userData: UserData
B. @State var userData: UserData
C. @Published var userData: UserData
D. @ObservedObject var userData: UserData

Solution

  1. Step 1: Understand property wrappers for ObservableObject in views

    Use @ObservedObject when the view receives an ObservableObject from outside and watches it.
  2. Step 2: Differentiate @StateObject and @ObservedObject

    @StateObject is for creating and owning the object inside the view; @ObservedObject is for observing an existing object.
  3. Final Answer:

    @ObservedObject var userData: UserData -> Option D
  4. Quick Check:

    Observe external ObservableObject with @ObservedObject [OK]
Hint: Use @ObservedObject to watch external ObservableObject [OK]
Common Mistakes:
  • Using @State for ObservableObject
  • Confusing @StateObject with @ObservedObject
  • Trying to use @Published in views
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard