如何在 SwiftUI 中核心数据变量发生变化时禁用按钮?

How to disabled a button when a core data variable changes in SwiftUI?

我正在尝试禁用基于视图模型计算的 属性 的按钮,但仅在重新加载视图后才被禁用。

这是视图模型:

  class VerifyFieldViewModel : ObservableObject {
    @ObservedObject var coreDataViewModel = CoreDataViewModel()
    func isValidFirstName() -> Bool {
        guard coreDataViewModel.savedDetails.first?.firstName?.count ?? 0 > 0 else {
            return false
        }
        return true
    }
    func isValidLastName() -> Bool {
        guard coreDataViewModel.savedDetails.first?.lastName?.count ?? 0 > 0 else {
            return false
        }
        return true
    }

    var isFirstNameValid : String {
        if isValidFirstName() {
       return ""
        } else {
        return "Name is empty"
        }
    }
    
    var isLastNameValid : String {
        if isValidLastName() {
       return ""
        } else {
        return "Surname is empty"
        }
    }
    
   var isSignUpComplete: Bool {
        if !isValidFirstName() || !isValidLastName() {
            return false
        }
        return true
    }
    }

这就是我禁用按钮的方式。

struct CartsView: View {
    @State var onboardingState: Int = 0
    @StateObject var coreDataViewModel = CoreDataViewModel()
    @ObservedObject var verifyFieldViewModel = VerifyFieldViewModel()
    var body: some View {
        ZStack {
            switch onboardingState {

            case 0 :
                VStack {
                detailOrder
                    .transition(transition)
                Spacer()
                bottomButton
                    .padding(30)
                }
            case 1 :
                VStack {
                detailOrder2. -> This is LivrareView
                    .transition(transition)
                    Spacer()
                    bottomButton
                        .padding(30)
                        .opacity(verifyFieldViewModel.isSignUpComplete ? 1 : 0.6)
                        .disabled(!verifyFieldViewModel.isSignUpComplete)
                }
            default:
                EmptyView()
            }
        }
}
}

这是核心数据视图模型:

class CoreDataViewModel  : ObservableObject {
    let manager = CoreDataManager.instance
    @Published var savedDetails : [Details] = []
    init() {
        fetchSavedDetails()
    }
    func fetchSavedDetails() {
        let request = NSFetchRequest<Details>(entityName: "Details")
        do {
            savedDetails = try manager.context.fetch(request)
        } catch let error {
            print("Error fetching \(error)")
        }
    }
    
    
    func saveContext() {
        DispatchQueue.main.async {
            self.manager.save()
            self.fetchSavedDetails()
        }
        }

}
struct LivrareView: View {
    @StateObject var coreDataViewModel = CoreDataViewModel()
    @EnvironmentObject var syncViewModel : SyncViewModel
    @ObservedObject var verifyFieldsViewModel = VerifyFieldsViewModel()
    var body: some View {
        let firstName = Binding(
            get: {coreDataViewModel.savedDetails.first?.firstName ?? ""},
            set: {coreDataViewModel.savedDetails.first?.firstName = [=13=]})
        
        let lastName = Binding(
            get: {coreDataViewModel.savedDetails.first?.lastName ?? ""},
            set: {coreDataViewModel.savedDetails.first?.lastName = [=13=]})
        
        ScrollView {
            VStack(alignment: .leading) {
                Text("First Name")
                    .padding(.top)
                    .foregroundColor(.orange)
                EntryField(placeHolder: "Name", prompt: $verifyFieldsViewModel.isFirstNameValid, field: firstName)
                    .onSubmit {
                        coreDataViewModel.saveContext()
                    }
                Text("Last Name")
                    .padding(.top)
                    .foregroundColor(.orange)
                EntryField(placeHolder: "Last Name", prompt: $verifyFieldsViewModel.isLastNameValid, field: lastName)
                
                    .onSubmit {
                        coreDataViewModel.saveContext()
                    }
            }
        }
    }

注意:它有效,但仅在重新加载视图时有效。

我怎样才能使这个工作?。我试过了

您不需要任何这些视图模型。只需在详细信息视图中使用 @FetchRequest in the View that contains the List and @ObservedObject。您可以将 TextField 直接绑定到托管对象,如 TextField($myObject.firstName)。从勾选核心数据框的 Xcode 应用程序模板开始,是了解它如何与 SwiftUI 一起工作的好方法。