Skip to content

Instantly share code, notes, and snippets.

@chockenberry
Created April 18, 2024 21:21
Show Gist options
  • Save chockenberry/c932d08a9200998caa2c06606164a1a2 to your computer and use it in GitHub Desktop.
Save chockenberry/c932d08a9200998caa2c06606164a1a2 to your computer and use it in GitHub Desktop.
Observable with backing store
//
// ContentView.swift
// ObservableTester
//
// Created by Craig Hockenberry on 4/18/24.
//
import SwiftUI
class BackingStore {
var value = 1
}
@Observable class Test {
let backingStore = BackingStore()
var x = 1
var y: Int {
get {
backingStore.value
}
set {
// NOTE: no @Published or Combine to propagate change.
//objectWillChange.send()
backingStore.value = newValue
}
}
func incrementBoth() {
x += 1
y += 1
}
var bothEven: Bool {
return (x % 2 == 0) && (y % 2 == 0)
}
}
struct ContentView: View {
@State private var test = Test()
var body: some View {
VStack(spacing: 10) {
Text("x = \(test.x)")
Text("y = \(test.y)")
Text("bothEven = \(test.bothEven)")
Button("Increment X") {
test.x += 1
}
Button("Increment Y") {
test.y += 1
}
Button("Increment Both") {
test.incrementBoth()
}
}
.padding()
}
}
#Preview {
ContentView()
}
@grantjbutler
Copy link

It's a little extra code for you to write, but you have the ability to indicate access and mutations to the observation system. The session Discover Observation in SwiftUI documents this. It's a little extra boilerplate, but you'd add some extra method calls to the getters and setters for y to opt it into observation.

var y: Int {
    get {
        access(keyPath: \.y)
        backingStore.value
    }
    set {
        withMutation(keyPath: \.y) {
            backingStore.value = newValue
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment