我正在使用 SwiftUI 和 Core Data 构建一个财务跟踪应用程序。在我的应用程序中,我有一个交易列表视图,用户可以在其中选择现有交易进行编辑。对于编辑视图,我对于选择这两种方法中的哪一种以及哪一种被认为是 Core Data SwiftUI 应用程序的“更好的实践”感到有点两难。
NSManagedObject
:表单字段直接绑定到 NSManagedObject 的属性,并且子上下文用于隔离保存和放弃更改的能力。可能看起来像这样:
struct EditTransactionView: View {
@ObservedObject var transaction: Transaction
var childContext: NSManagedObjectContext
init(transaction: Transaction, context: NSManagedObjectContext) {
self.transaction = transaction
self.childContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
self.childContext.parent = context
}
var body: some View {
Form {
TextField("Amount", text: $transaction.amount)
DatePicker("Date", selection: $transaction.date)
TextField("Notes", text: $transaction.notes)
}
.navigationBarItems(trailing: Button("Save") {
if self.childContext.hasChanges {
try? self.childContext.save()
}
})
}
}
@State
属性:通过这种方法,我可以使用 NSManagedObject 的数据初始化 @State 属性。当用户完成字段更新后,将手动更新 NSManagedObject。像这样的东西:
struct EditTransactionView: View {
var transaction: Transaction
@Environment(\.managedObjectContext) var moc
@State private var amount: String
@State private var date: Date
@State private var notes: String
init(transaction: Transaction) {
_amount = State(initialValue: transaction.amount)
_date = State(initialValue: transaction.date)
_notes = State(initialValue: transaction.notes)
}
var body: some View {
Form {
TextField("Amount", text: $amount)
DatePicker("Date", selection: $date)
TextField("Notes", text: $notes)
}
.navigationBarItems(trailing: Button("Save") {
transaction.amount = self.amount
transaction.date = self.date
transaction.notes = self.notes
try? self.moc.save()
})
}
}
注意:示例过于简化,并未在实际实现中使用。
这些都不理想。第一个每次 View 结构初始化时都会初始化一个新的上下文对象,这本质上是内存泄漏。第二个初始化一个具有依赖值的状态,这意味着它不是事实的来源。
为了解决这些问题,请创建一个状态结构,在父视图中的操作中创建子上下文和子对象一次,然后传递到详细信息中。