I am stuck with little problem , I can not change the value with .onAppear(), .onTapGesture() function and with a NavigationLink in SwiftUI
If anyone can tell me how to solve it ? Regards,
VIEW ONE
struct ContentView: View {
@StateObject var vm = ViewModel()
var body: some View {
NavigationView{
List{
ForEach(0..<4){ numero in
NavigationLink(
destination: DetailView().onAppear(){
//This function is not working
vm.takeNumber(number: numero)
},
label: {
Text(String(numero))
})
}
}
}
}
}
class ViewModel: ObservableObject {
@Published var numero:Int = 0
func takeNumber(number: Int) {
numero = number
}
}
VIEW TWO
struct DetailView: View {
@StateObject var vm = ViewModel()
var body: some View {
// My number is not updated
Text(String("My NUMBER : \(vm.numero)"))
}
}
CodePudding user response:
@StateObject
creates a fresh copy of your model.
Try changing it to
@ObservedObject var model: ViewModel
in DetailView
and pass it as argument in ContentView
.
CodePudding user response:
It looks like your approach is a bit incorrect. You are creating a new instance of your ViewModel
within each view. To correctly pass the StateObject
's instance forward, you will need to set it as an ObservedObject
in your DetailView
. StateObject
should be your source of truth for this view model. I suggest reading up on the fundamentals of these property wrappers.
For this code to work, the onAppear
should live within your DetailView
. Within the detail view, call your takeNumber
function with your number passed from your for loop. Then, reference your published value in your detail view. Viola!
struct ContentView: View {
@StateObject var vm = ViewModel()
var body: some View {
NavigationView{
List{
ForEach(0..<4){ numero in
NavigationLink(
destination: DetailView(vm: vm, number: numero),
label: {
Text(String(numero))
})
}
}
}
}
}
struct DetailView: View {
// Updated to observed object
// note how we are not constructing a new object here
@ObservedObject var vm: ViewModel
// Passing our number forward from our loop written in contentview
let number: Int
var body: some View {
// My number is not updated
Text(String("My NUMBER : \(vm.numero)"))
.onAppear {
vm.takeNumber(number: number)
}
}
}
class ViewModel: ObservableObject {
@Published var numero:Int = 0
func takeNumber(number: Int) {
numero = number
}
}