如何在 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 一起工作的好方法。
我正在尝试禁用基于视图模型计算的 属性 的按钮,但仅在重新加载视图后才被禁用。
这是视图模型:
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 一起工作的好方法。