如何用Core Data中的数据填充TextField并更新更改? [英] How to fill TextField with data from Core Data and update changes?

查看:248
本文介绍了如何用Core Data中的数据填充TextField并更新更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何使用核心数据"保存,编辑和删除数据.到目前为止,在这个强大的社区的帮助下,我已经成功地保存和删除了,但是我不知道如何编辑和更新当前保存的数据.

I am trying to learn how to Save, Edit and Delete data using Core Data. So far, with the help of this great community, I have managed to Save and Delete, but I don't know how to Edit and Update currently saved data.

这是我正在开发的应用程序的简单示例.这是包含来自核心数据的项目的列表.我在模态(AddItemView)上添加新的列表条目,并在EditItemView上删除它们. 我也想在AddItemView视图上编辑和更新数据.

Here is a simple example of an app I am working on. It is a list with items from Core Data. I am adding new list entries on a modal (AddItemView) and deleting them on EditItemView. I would like to edit and update data as well on the AddItemView view.

我设法将数据传递给TextField的提示,但是我想要的是:

I managed to pass data to hint of TextField, but what I wanted is:

  1. 将当前数据传递到TextField的文本并使其可编辑
  2. 点击后保存/更新数据
  1. pass the current data to text of TextField and make it editable
  2. Save/update the data after tapping

核心数据有1个实体:ToDoItem.它具有1个属性:title(字符串).代码:类定义,模块:当前产品模块.

Core Data has 1 Entity: ToDoItem. It has 1 Attribute: title (String). Codegen: Class Definition, Module: Current Product Module.

我在代码中添加了一些其他注释.

I have added some additional comments in the code.

ContentView

import SwiftUI

struct ContentView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(
        entity: ToDoItem.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \ToDoItem.title, ascending: true)
        ]
    ) var toDoItems: FetchedResults<ToDoItem>

    @State private var show_modal: Bool = false

    var body: some View {
        NavigationView {
            List{
                ForEach(toDoItems, id: \.self) {todoItem in

                    NavigationLink(destination: EditItemView(todoItem: todoItem)) {

                        Text(todoItem.title ?? "")
                        .font(.headline)
                    }
                }

            }
            .navigationBarTitle(Text("My List"))
            .navigationBarItems(trailing:
                Button(action: {
                    self.show_modal = true
                }) {
                    Text("Add")
                }.sheet(isPresented: self.$show_modal) {
                    AddItemView().environment(\.managedObjectContext, self.managedObjectContext)
                }
            )
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return ContentView().environment(\.managedObjectContext, context)
    }
}

AddItemView

import SwiftUI

struct AddItemView: View {

    @Environment(\.presentationMode) var presentationMode
    @Environment(\.managedObjectContext) var managedObjectContext

    @State private var title = ""

    var body: some View {
        NavigationView {
            ScrollView {

                TextField("to do item...", text: $title)
                    .font(Font.system(size: 30))

                Spacer()

            }
            .padding()
            .navigationBarTitle(Text("Add Item"))

            .navigationBarItems(
                leading:
                Button(action: {
                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Text("Cancel")
                },

                trailing:
                Button(action: {
                    let toDoItem = ToDoItem(context: self.managedObjectContext)
                    toDoItem.title = self.title

                    do {
                        try self.managedObjectContext.save()
                    }catch{
                        print(error)
                    }

                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Text("Done")
                }
            )

        }
    }
}

struct AddItemView_Previews: PreviewProvider {
    static var previews: some View {
        AddItemView()
    }
}

EditItemView

import SwiftUI

struct EditItemView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var todoItem: ToDoItem

    //I am only using this newTitle variable, because I don't know how to properly bind TextField to todoItem.title
    @State private var newTitle = ""

    var body: some View {
        ScrollView {

            TextField(todoItem.title != nil ? "\(todoItem.title!)" : "", text: $newTitle)

            //TextField("to do...", text: (todoItem.title != nil ? "\(todoItem.title!)" : ""))
            //ERROR
            //I need something like the above, but this gives me an error: Cannot convert value of type 'String' to expected argument type 'Binding<String>'

        }
        .padding()
        .navigationBarTitle(Text("Edit item"))
        .navigationBarItems(
            trailing:
            Button(action: {
                print("Delete")

                self.managedObjectContext.delete(self.todoItem)
                do {
                    try self.managedObjectContext.save()
                    self.presentationMode.wrappedValue.dismiss()
                }catch{
                    print(error)
                }

            }) {
                Text("Delete")
                    .foregroundColor(.red)
            }
        )
    }
}

struct EditItemView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        //Test data
        let todoItem = ToDoItem.init(context: context)
        todoItem.title = "Title"
        return EditItemView(todoItem: todoItem).environment(\.managedObjectContext, context)
    }
}

推荐答案

我将通过以下方式进行

TextField("_here_is_label_name_", text: $newTitle, onCommit: {
    self.todoItem.title = self.newTitle
    try? self.managedObjectContext.save()
})
.onAppear {
    self.newTitle = self.todoItem.title != nil ? "\(self.todoItem.title!)" : ""
}
.onDisappear {
    self.todoItem.title = self.newTitle
    try? self.managedObjectContext.save()
}

更新:添加了.onDisappear修饰符;可以使用专用的私有功能提取重复的代码,以进行良好的设计.

Update: added .onDisappear modifier; duplicated code can be extracted in dedicated private function to have good design.

这篇关于如何用Core Data中的数据填充TextField并更新更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆