Back to TILs

Swift state management

@State

Marks view's property as reactive. Like React's useState() or Vue's ref().
Triggers rendering when changed.

@Binding

Same concept as v-model in Vue. Marks view's property for 2-way binding.
Modifying the property inside view will propagate changes outside.

ObservableObject Protocol and @ObservedObject

class OrderModelController: ObservableObject {
    // @Published notifies watchers when order is modified
    @Published var order: Order
}


class SomeView: View {
    // This may cause issues during re-render when the @ObservedObject is owned by view and is not injected
    @ObservedObject var orderController = OrderModelController.load()
    // ^ Use @StateObject in this case.
}

In general you want something like this:

// SomeView.swift
class SomeView: View {
    @ObservedObject var injectedState: MyState
    init(myState: MyState) {
        self.injectedState = myState
    }
}

// SomeModel.swift
class SomeModel: ObservableObject {
    @Published var stateVariable: MyState

    init() {
        // initialize model
    }
}

// We are sharing the state from top to the bottom.
// This prop drilling can be mitigated by
// Entrypoint
// MyApp.swift
@main
struct MyApp: App {
    @StateObject private var myState: MyState

    init() {
        self._myState = StateObject(wrappedValue: MyState())
    }

    var body: some View {
        // View here
    }
}