带有 CoreData 的 TextField
Posted
技术标签:
【中文标题】带有 CoreData 的 TextField【英文标题】:TextField with CoreData 【发布时间】:2020-11-05 13:22:19 【问题描述】:目标:使用 coredata 在列表中拥有无限的文本字段,并具有 CRUD 功能。
目标示例,但没有 Coredata:
struct Item: Identifiable
let id = UUID()
var title: String
class TestItems: ObservableObject
@Published var items = [Item]()
struct ContentView: View
@ObservedObject var itemGroup = TestItems()
var body: some View
NavigationView
List
ForEach(itemGroup.items.indices, id:\.self) index in
TextField("Type Stuff Here", text: $itemGroup.items[index].title)
.onDelete(perform: removeRows)
.navigationBarTitle("Working Example")
.navigationBarItems(trailing: Button(action:
let stuff = Item(title: "")
itemGroup.items.append(stuff)
, label:
Text("Add")
))
func removeRows(at offsets: IndexSet)
itemGroup.items.remove(atOffsets: offsets)
我对 Coredata 的尝试:
import SwiftUI
import CoreData
struct ContentView: View
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [
NSSortDescriptor(keyPath: \Item.timestamp, ascending: true),
NSSortDescriptor(keyPath: \Item.title, ascending: true)
],
animation: .default)
private var items: FetchedResults<Item>
var body: some View
NavigationView
List
ForEach(items) item in
TextField("Type Response Here", text: $item.title) //<-- This returns an error "cannot find item in scope"
.onDelete(perform: deleteItems)
.navigationBarTitle("CoreData")
.navigationBarItems(trailing: Button(action:
addItem()
, label:
Text("Add Item")
))
private func addItem()
withAnimation
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
newItem.title = "Hello"
do
try viewContext.save()
catch
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
private func deleteItems(offsets: IndexSet)
withAnimation
offsets.map items[$0] .forEach(viewContext.delete)
do
try viewContext.save()
catch
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
我也尝试过将结构和类与 Coredata 一起使用(如我的示例),但如果可能的话,我无法找到将类保存到 Coredata 中的方法。
【问题讨论】:
【参考方案1】:您需要在 CoreData 对象上使用ObservedObject
,为此最好为行创建单独的子视图,例如
ForEach(items) item in
ItemView(item: item)
和ItemView
struct ItemView: View
@ObservedObject var item: Item
var body: some View
// now binding over item title is provided by ObservedObject wrapper
TextField("Type Response Here", text: $item.title)
更新:对可选属性的处理可能会有所不同,具体取决于预期的行为。这是可能的变体:
var body: some View
let text = Binding(
get: item.title ?? "" ,
set: item.title = $0
)
TextField("Type Response Here", text: text)
注意:在字段中输入文本不会保存 CoreData 对象,因此您需要考虑保存它的位置,可能的变体在 .onCommit
中为 TextField
。
【讨论】:
这会引发错误“无法将 'Binding以上是关于带有 CoreData 的 TextField的主要内容,如果未能解决你的问题,请参考以下文章
CoreData:带有privateQueueConcurrencyType的backgroundContext和子上下文之间的区别?
NSFetchRequest 带有用于递归 CoreData 实体关系的排序描述符
CoreData - 相当于使用带有示例的类别 - Swift
如何通过带有 FetchedResults 和 CoreData 的导航链接传递数据?
带有 NSFetchResultController 的 CoreData:使用 fetchObjects 中的属性进行的无效更新