是否可以使用关键路径将值保存到CoreData ?



在父视图中,我有这个:

LongPressEditableText(contents: "(workout.name ?? "")", context: workout, keyPath: WorkoutEntity.name)

在CoreData中引用WorkoutEntity的字符串字段。

LongPressEditableText是一个组件,它通常只是一个Text(),但是当长按时,变成一个具有相同内容的TextField,可编辑。在提交时,它应该更新UI(它做得很好),但它也应该将新值保存到CoreData中的适当位置。

struct LongPressEditableText: View {

@State var contents: String

@Environment(.managedObjectContext) private var viewContext

var context: NSObject
var keyPath: KeyPath<NSObject, String?>

@State var inEditMode: Bool = false

var body: some View {
if inEditMode {
TextField("test", text: $contents)
.onSubmit {
context[keyPath: keyPath] = contents
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error (nsError), (nsError.userInfo)")
}

inEditMode.toggle()

}
} else {
Text(contents)
.onLongPressGesture {
inEditMode.toggle()
}
}
}
}

现在,我得到了两个错误。在我的父视图Cannot convert value of type 'KeyPath<WorkoutEntity, String?>' to expected argument type 'KeyPath<NSObject, String?>'和LongPressEditableText视图Cannot assign through subscript: key path is read-only

我可以通过强制KeyPath来解决第一个问题,但这不是一个解决方案,因为我希望可编辑字段与许多具有字符串字段的不同实体一起工作,所以我希望它是通用的。第二次我被难住了,这是我最接近成功的一次。

"泛型不是我主要关心的…">,是的,这是因为它是一个非常有用的解决方案,告诉编译器和运行时在文本字段中使用什么类型的对象。

首先,因为这是核心数据,我们不应该使用NSObject,而是NSManagedObject,所以让我们用一个继承自NSManagedObject的类型来创建视图泛型,然后在属性中使用泛型。

struct LongPressEditableText<ManagedObject: NSManagedObject>: View {
@Environment(.managedObjectContext) private var viewContext
@State private var contents: String = ""
@State var object: ManagedObject
var keyPath: ReferenceWritableKeyPath <ManagedObject, String?>

注意,属性object(代码中的上下文)被声明为泛型类型,并且keyPath也被定义为持有相同的类型。我也从KeyPath更改为ReferenceWritableKeyPath,因为泛型类型是一个类,我们想使用密钥路径来更新对象。

在这里使用字段是一个例子,因为视图是泛型的,编译器可以推断出泛型类型是Item,并检查它是否有一个属性text

struct DetailView: View {
@ObservedObject var item: Item
var body: some View {
VStack {
LongPressEditableText(object: item, keyPath: .text)
}
.padding()
}
}

相关内容

  • 没有找到相关文章

最新更新