Enes Karaosman
Enes Karaosman

Reputation: 2067

How to properly change Child view's (@State/@Binding) variable from ParentView via function? (not in constructor)

I want to achieve something similar to below;

struct PlaygroundView: View {
    var body: some View {
        NavigationView {
            Child()
                .myTapGesture {
                    print("outer gesture")
                }
        }
    }
}

struct Child: View {

    @State private var myTapGesture: () -> Void = { print("inner gesture") }

    var body: some View {
        Text("Child")
        .onTapGesture(perform: myTapGesture)
    }

    func myTapGesture(action: @escaping () -> Void) -> Child {
        self.myTapGesture = action
        return self
    }

}

The main reason for my purpose is not to have a crowded init.

Upvotes: 1

Views: 513

Answers (3)

Asperi
Asperi

Reputation: 257493

Here is possible approach

struct Child: View {

    private var myTapGesture: () -> Void = { print("inner gesture") }

    var body: some View {
        Text("Child")
            .onTapGesture(perform: myTapGesture)
    }

    func myTapGesture(action: @escaping () -> Void) -> Child {
        var myCopy = self
        myCopy.myTapGesture = action
        return myCopy
    }
}

Update: added demo (Xcode 11.4)

demo

Upvotes: 2

Simon
Simon

Reputation: 1840

If the child has a @Binding which it receives from the parent. Then it automatically updates when the parents @State updates. See e.g.

struct Parent: View {

    @State var myVar = 1

    var body: some View {
        Child(myVar: self.$binding)
    }

    func updated() { //when calling this function the @Binding in Child will also update
      self.myVar = 2
    }
}


struct Child: View {

    @Binding var myVar: Int

    var body: some View {
        Text(self.myVar)
    }
}

Upvotes: 0

Cuneyt
Cuneyt

Reputation: 981

There's already a way to update SwiftUI Views with modifiers. Have a look at this:

struct TapViewModifier: ViewModifier {

    var onTapGesture: () -> Void = { print("default implementation here") }

    func body(content: Content) -> some View {
        content
            .onTapGesture(perform: onTapGesture)
    }
}

And the usage is:

struct PlaygroundView: View {

    var body: some View {
        NavigationView {
            Child()
                .modifier(TapViewModifier(onTapGesture: { print("your new implementation") }))
        }
    }
}

Upvotes: 0

Related Questions