UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

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.