簡體   English   中英

無法在 SwiftUI 中初始化 @StateObject ViewModel

[英]Unable to initialize @StateObject ViewModel in SwiftUI

我試圖在 ViewModel 中注入 managedObjectContext 並且由於某種奇怪的原因它拋出了一個奇怪的錯誤。

struct ContentView: View {
   
    @Environment(\.managedObjectContext) var viewContext
    @StateObject var addBudgetVM: AddBudgetViewModel
    
    init() {
        // THIS LINE CAUSES ISSUES 
        addBudgetVM = AddBudgetViewModel(context: viewContext)
    }
    
    var body: some View {
       // some code here
    }
    
}

Cannot assign to property: 'addBudgetVM' is a get-only property

這里是 AddBudgetViewModel 的實現

import Foundation
import CoreData

class AddBudgetViewModel: ObservableObject {
    
    @Published var name: String = ""
    var context: NSManagedObjectContext
    
    init(context: NSManagedObjectContext) {
        self.context = context
    }
    
    func save() {
        
    }
    
}

您可以在沒有參數的情況下初始化視圖模型,並在視圖模型內部聲明 de environment

struct ContentView: View {
@StateObject var addBudgetVM: AddBudgetViewModel = AddBudgetViewModel()

  var body: some View {
   // some code here
}

}

視圖模型:

class AddBudgetViewModel: ObservableObject {

@Published var name: String = ""
@Environment(\.managedObjectContext) var viewContext
    
func save() {
    
}

}

我發現最好的方法是從超級視圖注入視圖模型。 這很好地將使用視圖模型的視圖與創建視圖模型分開。 它提高了可測試性,因為它可以輕松注入模擬視圖模型。

就像是:


struct ParentView: View {
      @Environment(\.managedObjectContext) var viewContext

      var body: some View {
          //...
          AddBudgetView(viewModel: AddBudgetViewModel(context: viewContext))
          //...
      }
}


struct AddBudgetView: View {

      viewModel: AddBudgetViewModel 

      var body: some View {
          // ...
      }
}

class AddBudgetViewModel: ObservableObject {

    private (set) var context: NSManagedObjectContext

    init(context: NSManagedObjectContext) {
    
        self.context = context
    }

   func save() {
    
   }
}

我什至可能不會在視圖模型中包含 Core Data 代碼。 我會將所有這些放在一個主模型中,並將主模型實例傳遞給視圖模型初始化程序而不是托管對象上下文。 然后視圖模型可以調用主模型上的方法來創建和保存項目。 通過這種方式,您的視圖模型與存儲實現細節隔離開來,您可以對存儲進行更改,例如替換核心數據,而無需到處觸摸視圖模型。

您需要像這樣實例化StateObject

 _addBudgetVM = StateObject(wrappedValue: AddBudgetViewModel(context: viewContext))

盡管Apple 建議不要這樣做

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM