UI赢得了带有Coredata的实时更改
我有一个Swiftui + Coredata简单的TODO应用程序,一切正常,但是我的UpdateTodo函数应该可以处理单击todo的单击并从完成转换为撤消,反之亦然,但无法正常工作。 当我单击UI中什么都没发生时,但是当我回到屏幕回到Todos屏幕上时,我可以看到UI更改,也可以持续存在,因此当我关闭并打开应用程序时,更改为反映在应用程序中。 因此,我的问题是“ ISDONE”属性并未实时在UI中切换,并且只有当视图重新出现时,它实际上显示了已进行的更改。
ViewModel(Coredata):
class TodoViewModel:ObservableObject {
let container: NSPersistentContainer
@Published var categories = [CategoryTodo]()
@Published var todos = [Todo]()
init() {
container = NSPersistentContainer(name: "UniversityProject")
container.loadPersistentStores { (description, error) in
if let error = error {
fatalError("Error: \(error.localizedDescription)")
}
}
}
//MARK: - Todos
func getTodos() {
let request = NSFetchRequest<Todo>(entityName: "Todo")
let sort = NSSortDescriptor(key: #keyPath(Todo.dateCreated), ascending: false)
request.sortDescriptors = [sort]
do {
try todos = container.viewContext.fetch(request)
} catch {
print("Error getting data. \(error)")
}
}
func addTodo(todo text: String, category categoryName:String) {
let newTodo = Todo(context: container.viewContext)
newTodo.todo = text
newTodo.category = categoryName
newTodo.id = UUID().uuidString
newTodo.isDone = false
newTodo.dateCreated = Date()
saveTodo()
}
func saveTodo() {
do {
try container.viewContext.save()
getTodos()
} catch let error {
print("Error: \(error)")
}
}
func deleteTodo(indexSet: IndexSet) {
let todoIndex = indexSet[indexSet.startIndex]
let object = todos[todoIndex]
container.viewContext.delete(object)
saveTodo()
}
func updateTodo(item: Todo) {
item.setValue(!item.isDone, forKey: "isDone")
saveTodo()
}
}
TodoSview:
struct TodosView: View {
@EnvironmentObject var viewModel: TodoViewModel
let categoryName:String
var body: some View {
List {
ForEach(viewModel.todos.filter{$0.category == categoryName}) { item in
TodoItem(item: item)
.onTapGesture {
withAnimation(.linear) {
viewModel.updateTodo(item: item)
}
}
}
.onDelete(perform: viewModel.deleteTodo)
}.onAppear { viewModel.getTodos() }
.navigationBarTitle(categoryName)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
HStack {
EditButton()
NavigationLink(destination: AddTodoView(category: categoryName)) {
Image(systemName: "plus.circle")
.resizable()
.foregroundColor(.blue)
.frame(width: 25, height: 25)
}
}
}
}
}
}

I have a SwiftUI + CoreData simple Todo app, and everything works properly, but my updateTodo function which is supposed to handle the click on a todo and turn in from done to undone and vice versa, isn't working properly.
When I click on a todo nothing happens in the UI, but when I go a screen back and come back to the todos screen, I can see the UI change, also it does persist so when I close and open the app the change is being reflected in the app.
So my problem is that the 'isDone' property is not being toggled in the UI in real-time, and only when the view reappears it actually shows the change that has been made.
ViewModel (CoreData) :
class TodoViewModel:ObservableObject {
let container: NSPersistentContainer
@Published var categories = [CategoryTodo]()
@Published var todos = [Todo]()
init() {
container = NSPersistentContainer(name: "UniversityProject")
container.loadPersistentStores { (description, error) in
if let error = error {
fatalError("Error: \(error.localizedDescription)")
}
}
}
//MARK: - Todos
func getTodos() {
let request = NSFetchRequest<Todo>(entityName: "Todo")
let sort = NSSortDescriptor(key: #keyPath(Todo.dateCreated), ascending: false)
request.sortDescriptors = [sort]
do {
try todos = container.viewContext.fetch(request)
} catch {
print("Error getting data. \(error)")
}
}
func addTodo(todo text: String, category categoryName:String) {
let newTodo = Todo(context: container.viewContext)
newTodo.todo = text
newTodo.category = categoryName
newTodo.id = UUID().uuidString
newTodo.isDone = false
newTodo.dateCreated = Date()
saveTodo()
}
func saveTodo() {
do {
try container.viewContext.save()
getTodos()
} catch let error {
print("Error: \(error)")
}
}
func deleteTodo(indexSet: IndexSet) {
let todoIndex = indexSet[indexSet.startIndex]
let object = todos[todoIndex]
container.viewContext.delete(object)
saveTodo()
}
func updateTodo(item: Todo) {
item.setValue(!item.isDone, forKey: "isDone")
saveTodo()
}
}
TodosView:
struct TodosView: View {
@EnvironmentObject var viewModel: TodoViewModel
let categoryName:String
var body: some View {
List {
ForEach(viewModel.todos.filter{$0.category == categoryName}) { item in
TodoItem(item: item)
.onTapGesture {
withAnimation(.linear) {
viewModel.updateTodo(item: item)
}
}
}
.onDelete(perform: viewModel.deleteTodo)
}.onAppear { viewModel.getTodos() }
.navigationBarTitle(categoryName)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
HStack {
EditButton()
NavigationLink(destination: AddTodoView(category: categoryName)) {
Image(systemName: "plus.circle")
.resizable()
.foregroundColor(.blue)
.frame(width: 25, height: 25)
}
}
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
没有所有相关代码,我只能猜测并建议您尝试类似的事情:
或
without all relevent code, I can only guess and suggest you try something like these:
or