How to run child function from parent?

0

I want to call childFunction() demo ChildView by pressing the button in the parent view.

import SwiftUI

struct ChildView: View {
    
    func childFunction() {
        print("I am the child")
    }

    var body: some View {
      Text("I am the child")
    }
}

struct ContentView: View {
    var function: (() -> Void)?

    var body: some View {
        ChildView()
        
        Button(action: {
            self.function!()
        }, label: {
            Text("Button")
        })
    }
}

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

Update: Thanks @RajaKishan, it works, but I need it working also recursively

import SwiftUI

struct ContentView: View {
    @State var text: String = "Parent"
    var isNavigationViewAvailable = true
    
    func function() {
        print("This view is \(text)")
    }
    
    var body: some View {
        
        VStack {
            if isNavigationViewAvailable  {
                Button(action: {
                    function()
                }, label: {
                    Text("Button")
                })
            }
           
            
            if isNavigationViewAvailable {
                NavigationView {
                    List {
                        NavigationLink("Child1") {
                            ContentView(text: "Child1", isNavigationViewAvailable: false)
                        }
                        NavigationLink("Child2") {
                            ContentView(text: "Child2", isNavigationViewAvailable: false)
                        }
                        NavigationLink("Child3") {
                            ContentView(text: "Child3", isNavigationViewAvailable: false)
                        }
                    }
                }
            }
        }
    }
}

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

Maybe is is not the best looking example, but the question is, how to force the button to run function of it's child after user visited corresponding child.

Like, on start when user presses the button it prints "This view is Parent". After user comes to child1 the button press should print "This view is Child1" as so on. So, the function that button runs should be referenced from the last child.

Update: In the end I wrote this solution.

Update: I received feedback, asking me for clarification. No problem. I hope it'll help somebody.:)

Clarification: I did not enclose the whole code, just used a simple example. But I needed this in my implementation of a tree-like generated menu: when each item in the menu has or does not have its children. Pressing on parent object user comes into child objects. And here I needed to be able to come back from a child object to parent, but call this dismiss function from the parent object. For this I used the following code and referred to this function to each parent object:

@Environment(\.presentationMode) var presentationMode
 presentationMode.wrappedValue.dismiss()
ios swift swiftui
2021-11-24 05:44:05
1

1

You can create an object for a ChildView.

struct ChildView: View {
 
    func childFunction() {
        print("I am the child")
    }
    
    var body: some View {
        Text("I am the child")
    }
}

struct ContentView: View {
    
    let childView = ChildView()
    
    var body: some View {
        childView
        Button(action: {
            childView.childFunction()
        }, label: {
            Text("Button")
        })
    }
}


EDIT : For the list, you can use the array of the model and call the destination function by index.

Here is the simple child-parent example.

struct ChildView: View {
    var text: String
    
    func childFunction() {
        print("This view is \(text)")
    }
    
    var body: some View {
        Text("I am the child")
    }
}



struct ContentView55: View {
    
    @State private var arrData = [Model(title: "Child1", destination: ChildView(text: "Child1")),
                                           Model(title: "Child2", destination: ChildView(text: "Child2")),
                                           Model(title: "Child3", destination: ChildView(text: "Child3"))]
    
    var body: some View {
        
        VStack {
            Button(action: {
                arrData[1].destination.childFunction()
            }, label: {
                Text("Button")
            })
            
            NavigationView {
                SwiftUI.List(arrData) {
                    NavigationLink($0.title, destination: $0.destination)
                }
            }
        }
    }
    
}
struct Model: Identifiable {
    var id = UUID()
    var title: String
    var destination: ChildView
}

Note: You need to index for the row to call child function.

2021-11-24 07:34:52

Hi. Thanks for the answer. It works. But in the case of recursive View struct when ContentView has ContentView childs created via NavigationLinks, how this could be solved as Value type cannot have a stored property that recursively contains it ?
Degtiarev Aleksei

@DegtiarevAleksei can you please add one example to your question?
Raja Kishan

Updated the question
Degtiarev Aleksei

@DegtiarevAleksei I have added the edit part. This might be helpful.
Raja Kishan

Thank you for the answer, but after I compiled the button always returns "This view is Child2"
Degtiarev Aleksei

@DegtiarevAleksei It is because I have set index 1 (arrData[1]) in the button action. read my note.
Raja Kishan

This might not work as expected because views in SwiftUI are structs, which means they are passed by value, thus copied every time they are circulated. In the end, you end up with multiple, distinct ChildView instances, so you might end up calling the child function on another view than the one you expect to.
Cristik

@Cristik yes I think this is right to create multiple instances for each child view call. Because it behaves differently for each occurrence.
Raja Kishan

In other languages

This page is in other languages

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................