0

I'm currently working through Paul Hudson's 100 Days of SwiftUI bootcamp and I'm stuck at a challenge which asks to transfer objects from a struct (View) into a class (ViewModel) in order to create a MVVM-Architecture in the project. However when initializing a certain variable inside my struct initializer I get a runtime-warning So here are the initialized objects in my view struct:

@StateObject private var viewModel = EditViewViewModel()

@Environment(\.dismiss) var dismiss
var onSave: (Location) -> Void

initializer for struct:

init(location: Location, onSave: @escaping (Location) -> Void) {
    self.onSave = onSave
    viewModel.location = location // WARNING: Accessing StateObject's object without being installed on a View. This will create a new instance each time.
}

This is the variable that's causing problems and the initializer of my ViewModel:

    var location: Location
    
    init() {
        self.location = Location(id: UUID(), name: "", description: "", latitude: 0.0, longitude: 0.0)
        self.name = ""
        self.description = ""
    }

1 Answers1

0

This question is duplicate of this one.

Here is a minimum example of SwiftUI with MVVM. Put your location update to the onAppear, remove it from init.

import SwiftUI

struct NumberView: View {
    @StateObject private var viewModel = NumberViewModel()

    init() {
        // Accessing StateObject's object without being installed on a View. This will create a new instance each time.
        // viewModel.increaseNum()
    }

    var body: some View {
        VStack {
            Text("Num: \(viewModel.num)")
            Button("Increase num", action: {
                // No warnings about accessing StateObject's object without being installed on a View
                viewModel.increaseNum()
                print("New num to viewModel: \(viewModel.num)")
            })
        }
        .onChange(of: viewModel.num) { newNum in
            print("New num from viewModel: \(newNum)")
        }
        .onAppear {
            // No warnings about accessing StateObject's object without being installed on a View
            viewModel.increaseNum()
        }
    }
}

class NumberViewModel: ObservableObject {
    @Published private(set) var num: Int = 0

    func increaseNum() {
        num += 1
    }
}
Denis Kutlubaev
  • 15,320
  • 6
  • 84
  • 70