Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call parent's function from child of a child in SwiftUI

Tags:

swiftui

I have ParentView that passes a function to a ChildView, then the function is called in the ParentView when a button is clicked in the ChildView. But what if I would want a Child of the Child to call the function? Would I need to pass the function further down, or is there a way to make a function somehow accessible throughout the environment?

struct ParentView: View {
    func parentFunction() {
        print("parentFunction called")
    }

    var body: some View {
        ChildView(p: parentFunction)
    }
}


struct ChildView: View {
    var p: () -> ()
    var body: some View {
        VStack {
            Text("child view")
            Button(action: {
                self.p()
            }) {
                Image(systemName: "person")
            }
        }
    }
}
like image 287
DevB2F Avatar asked Sep 05 '25 03:09

DevB2F


1 Answers

Yes it is possible to do using custom defined EnvironmentKey and then use it set parent view environment function, which will be available for all subviews.

Here is a demo of approach

struct ParentFunctionKey: EnvironmentKey {
    static let defaultValue: (() -> Void)? = nil
}

extension EnvironmentValues {
    var parentFunction: (() -> Void)? {
        get { self[ParentFunctionKey.self] }
        set { self[ParentFunctionKey.self] = newValue }
    }
}

struct ParentView: View {
    func parentFunction() {
        print("parentFunction called")
    }

    var body: some View {
        VStack {
            ChildView()
        }
        .environment(\.parentFunction, parentFunction) // set in parent
    }
}

struct ChildView: View {
    @Environment(\.parentFunction) var parentFunction // join in child
    var body: some View {
        VStack {
            Text("child view")
            Button(action: {
                self.parentFunction?() // < use in child
            }) {
                Image(systemName: "person")
            }
            Divider()
            SubChildView()
        }
    }
}

struct SubChildView: View {
    @Environment(\.parentFunction) var parentFunction // join in next subchild
    var body: some View {
        VStack {
            Text("Subchild view")
            Button(action: {
                self.parentFunction?() // use in next subchild
            }) {
                Image(systemName: "person.2")
            }
        }
    }
}
like image 53
Asperi Avatar answered Sep 07 '25 19:09

Asperi