I have an app wherein once navigated to a second page and shown some results, the user has the option of running the same function but with some different parameters.
I am stuck on figuring out how to run the func that is inside my initial screen from within my second...
I have tried several methods but seem to get stuck. I have tried moving the func to my @main
struct as well and having it be global. seems there are some linking issues as I'm doing it wrong. I have placed ContentView.doFunction()
as an example of where I need to run the func from, this obviously doesn't work and is a bit more pythonic..
I will provide a very basic reproduction of the code.
struct ContentView: View {
@State private var readyToNavigate: Bool = false
var body: some View {
NavigationStack {
VStack {
Button(action: doFunction, label: {
Text("Button")
})
.navigationDestination(isPresented: $readyToNavigate) {
secondPage()}
.navigationTitle("Test")
}
}
}
func doFunction() {
Task {
let example = await "This is running an async operation"
print(example)
}
readyToNavigate = true
}
}
#Preview {
ContentView()
}
and from the other view which is in a seperate swift file...
struct secondPage: View {
var body: some View {
Button("run func from first page", action: {
// ContentView.doFunction()
print("running async func from ContentView")
})
}
}
#Preview {
secondPage()
}
In SwiftUI use async/await with .task
not Task {}
, e.g.
struct ContentView: View {
@State private var readyToNavigate: Bool = false
@State private var isRunning = false
var body: some View {
NavigationStack {
VStack {
Button(isRunning ? "Stop" : "Start") {
isRunning.toggle()
}
.navigationDestination(isPresented: $readyToNavigate) {
SecondPage()
}
.navigationTitle("Test")
}
}
.task(id: isRunning) { // runs on appear and cancelled and restarted when id changes, cancelled on dissapear
if isRunning == false { return }
await doFunction()
isRunning = false
}
}
func doFunction() async {
let example = await "This is running an async operation"
print(example)
readyToNavigate = true
}
}
If you want to restart the function from a child View
then you can pass a Binding
in to allow write access to the same State that is used as the id
in .task
.