2

I have something of the following:

struct ContentView: View {
    @State var a = 0 {
        didSet {
            print("Change detected in Parent")
        }
    }
    var body: some View {
        VStack{
            Text(String(self.a))
            Content2(a: self.$a)
        }
    }
}

struct Content2: View {
    @Binding var a: Int {
        didSet {
            print("Change detected in Child")
        }
    }

    var body: some View {
        Text(String(a)).onTapGesture {
            if self.a == 1 {
                self.a = 2
            }else {
                self.a = 1
            }

        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


Why is the didSet of the parent never called? As it is clearly changing. How can I make sure it gets called or notified in some other way?

It is important to me to take notice of the change on the ContentView and not outsource this to a PublishableObject. As I want to make further changes on the ContentView once this change has been detected. Catching the didSet on an outsourced Class would not help.

To clear things up my use case is as follows: I am counting up a Int on the child View. Once this Int reached a certain number it should trigger a new Firebase getDocuments function on the ParentView.

Simon
  • 1,754
  • 14
  • 32
  • 1
    Does this answer your question? [How can I run an action when a state changes?](https://stackoverflow.com/questions/56550713/how-can-i-run-an-action-when-a-state-changes) – rbaldwin May 30 '20 at 14:31
  • @Asperi or rather a feature of `@State`. It will work on regular old property wrappers. – Sweeper May 30 '20 at 14:33
  • No this question did not help. As described I need to notice the ```didSet ```on the ```ContentView ``` Struct and not in a outsourced class. This is due to me wanting to act on the ```didSet``` in the ```ContentView```. Or is there a way for me to tell the ```ObservableObject class``` to call a function on the ```ContentView```? – Simon May 30 '20 at 15:39
  • 1
    @Simon, Views should be lightweight dumb static objects that just describe the view composition. The View Model (implemented as an ObservableObject, for example) should be the ones reacting to events and changing the model. – New Dev May 30 '20 at 15:50

1 Answers1

2

Here is a solution for your use-case

struct ContentView_: View {
    @State var a = 0

    var body: some View {
        let counterBinding = Binding( // << proxy biding
            get: { self.a },
            set: {
                self.a = $0  // decision case below
//                if $0 > CONSTANT {
//                   // ... call getDocuments here
//                }
            }
        )
        return VStack{
            Text(String(self.a))
            Content2(a: counterBinding) // inject proxy !!
        }
    }
}

struct Content2: View {
    @Binding var a: Int

    var body: some View {
        Text(String(a)).onTapGesture {
            if self.a == 1 {
                self.a = 2
            }else {
                self.a = 1
            }
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690