LAST CHANCE: Save 50% on all my Swift books and bundles! >>

Calling Functions of Sub-views

Forums > SwiftUI

My question is essentially this: if I have a view DetailView within another view MainView, how can I call a function of DetailView from MainView? Here's a simple example of what I'm trying to acheive:

struct MainView: View {    
    var body: some View {
        VStack {
            Button("Increase Count") {
                // Call 'stepCount'
            }
            DetailView()
        }
    }
}

struct DetailView: View {
    @State private var count = 0
    var body: some View {
        Text("The count is: \(self.count)")
    }
    func stepCount() {
        count += 1
    }
}

I'd like stepCount() to be called whenever the button is pressed. Clearly, I could just move the button inside DetailView, but in more complex projects this isn't always practical.

Here is one idea I had that doesn't work, but I thought it might be worth sharing it anyway:

struct MainView: View {
    var detail : DetailView = DetailView()
    var body: some View {
        VStack {
            Button("Increase Count") {
                self.detail.stepCount()
            }
            detail
        }
    }
}

I've found through print statements that the stepCount function is performed when the button is pressed, but the text in DetailView doesn't change.

I'd be hugely grateful if anyone could suggest a solution, and also if anyone could explain why the idea above doesn't work!

3      

You wouldn't call a DetailView function from MainView.

You would instead use some combination of bindings and/or environment objects to update a value shared between the two views.

3      

struct MainView: View {
    @State
    private var count: Int = 0
    var body: some View {
        VStack {
            Button("Increase Count") {
                // Call 'stepCount'
                count += 1
            }
            DetailView(count: $count)
        }
    }
}

struct DetailView: View {
    @Binding
    var count: Int
    var body: some View {
        Text("The count is: \(self.count)")
    }
//    func stepCount() {
//        count += 1
//    }
}

3      

You really only need the @Binding in DetailView if count can be changed inDetailView and the changed value then fed back up to MainView. Otherwise, simply passing in the value of count would suffice.

struct MainView: View {
    @State
    private var count: Int = 0
    var body: some View {
        VStack {
            Button("Increase Count") {
                self.count += 1
            }
            DetailView(count: count)
        }
    }
}

struct DetailView: View {
    let count: Int

    var body: some View {
        Text("The count is: \(count)")
    }
}

Because whenever count is updated in MainView, the DetailView will get redrawn with the new value anyway.

3      

Hacking with Swift is sponsored by Essential Developer.

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until July 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.