Search code examples
iosswiftstateswiftui

How can I run an action when a state changes?


enum SectionType: String, CaseIterable {
    case top = "Top"
    case best = "Best"
}

struct ContentView : View {
    @State private var selection: Int = 0

    var body: some View {
        SegmentedControl(selection: $selection) {
            ForEach(SectionType.allCases.identified(by: \.self)) { type in
                Text(type.rawValue).tag(type)
            }
        }
    }
}

How do I run code (e.g print("Selection changed to \(selection)") when the $selection state changes? I looked through the docs and I couldn't find anything.


Solution

  • You can't use didSet observer on @State but you can on an ObservableObject property.

    import SwiftUI
    import Combine
    
    final class SelectionStore: ObservableObject {
        var selection: SectionType = .top {
            didSet {
                print("Selection changed to \(selection)")
            }
        }
    
        // @Published var items = ["Jane Doe", "John Doe", "Bob"]
    }
    

    Then use it like this:

    import SwiftUI
    
    enum SectionType: String, CaseIterable {
        case top = "Top"
        case best = "Best"
    }
    
    struct ContentView : View {
        @ObservedObject var store = SelectionStore()
    
        var body: some View {
            List {
                Picker("Selection", selection: $store.selection) {
                    ForEach(FeedType.allCases, id: \.self) { type in
                        Text(type.rawValue).tag(type)
                    }
                }.pickerStyle(SegmentedPickerStyle())
    
                // ForEach(store.items) { item in
                //     Text(item)
                // }
            }
        }
    }