0

I want to be able to dynamically return the right variable to be used as a @Binding in a SwiftUI view however when I create a function to return something as Binding I no longer receive the didSet call on that variable. I'm not sure if this is unsupported behavior or I'm doing something wrong.

Here is an example

struct ContentView: View {
    @StateObject var dataStore = DataStore()
    
    var body: some View {
        VStack {
            Toggle("val1", isOn: $dataStore.val1)
            Toggle("val2", isOn: dataStore.boundVal2())
        }
        
    }
}

class DataStore: ObservableObject {
    
    @AppStorage("val1")
    var val1: Bool = false {
        didSet {
            print("did set val1")
        }
    }
    
    @AppStorage("val2")
    var val2: Bool = false {
        didSet {
            print("did set val2")
        }
    }
    
    func boundVal2() -> Binding<Bool> {
        return $val2
    }
}

When you toggle the first value you get the didSet call, but when you toggle the second value you don't get it.

A. Z.
  • 198
  • 1
  • 9
  • you could find the answer here https://stackoverflow.com/questions/63171806/willset-not-being-called-on-swiftuis-new-appstorage-property – belal medhat Feb 08 '22 at 21:50
  • The only SwiftUI wrapper that works reliably in a class is Published when inside and ObservableObject. The rest won’t work as you are expecting. AppStorage and Binding don’t belong there, only in a SwiftUI View – lorem ipsum Feb 09 '22 at 01:21
  • @loremipsum the DataStore class conforms to ObservableObject, as of iOS 14.5 putting AppStorage properties in an ObservableObject is supported behavior, see https://developer.apple.com/documentation/ios-ipados-release-notes/ios-ipados-14_5-release-notes – A. Z. Feb 11 '22 at 01:41

1 Answers1

0

It turns out that you need to use a Binding object to pass it back, like so:

    func boundVal2() -> Binding<Bool> {
        Binding(
            get: { self.val2 },
            set: { self.val2 = $0 }
        )
    }
A. Z.
  • 198
  • 1
  • 9
  • Just a heads up that this could potentially inject a retention cycle. `self` should be handled properly here to avoid any memory leaks. – Fernando Mata Jan 05 '23 at 17:19