Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
StateObject vs. ObservableObject
// If you run this in a playground in Xcode 12, you can see the difference in behavior in the live view.
import SwiftUI
import PlaygroundSupport
class Counter: ObservableObject {
@Published var count: Int
init(_ initialCount: Int) {
self.count = initialCount
}
func increment() {
count += 1
}
func decrement() {
count -= 1
}
}
struct Counters: View {
@State var useFirstCounter = true
@StateObject var counter1 = Counter(0)
@StateObject var counter2 = Counter(0)
var body: some View {
VStack {
Counter1(counter: useFirstCounter ? counter1 : counter2)
Counter2(counter: useFirstCounter ? counter1 : counter2)
Button("Switch Counter") {
useFirstCounter.toggle()
}
}
}
}
// The Counter in this view will always be the one passed in from the parent view.
struct Counter1: View {
@ObservedObject var counter: Counter
init(counter: Counter) {
self.counter = counter
}
var body: some View {
HStack {
Button { counter.decrement() } label: { Image(systemName: "minus.circle") }
Text("\(counter.count)")
Button { counter.increment() } label: { Image(systemName: "plus.circle") }
}
}
}
// The Counter in this view will initially be set to the one passed in from the parent,
// but in later view updates, this will keep using that same instance every time, even
// if the parent later passes in a different Counter.
struct Counter2: View {
@StateObject var counter: Counter
init(counter: Counter) {
self._counter = StateObject(wrappedValue: counter)
}
var body: some View {
HStack {
Button { counter.decrement() } label: { Image(systemName: "minus.circle") }
Text("\(counter.count)")
Button { counter.increment() } label: { Image(systemName: "plus.circle") }
}
}
}
PlaygroundPage.current.setLiveView(Counters())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.