ios - DetailView 中的 SwiftUI 核心数据绑定(bind)文本字段

标签 ios core-data swiftui

我有一个 SwiftUI 应用程序,其 SwiftUI 应用程序生命周期包括主从类型 从 CoreData 驱动的列表。我在 ContentView 和 NavigationLinks 中有标准列表 到细节 View 。我将核心数据实体对象传递给 Detailview。

我的努力是在 DetailView 中设置与 TextFields 的绑定(bind)以进行数据输入 和编辑。我试图创建一个我无法工作的初始化程序。我有 只能使其与以下内容一起使用。分配初始值 在体内似乎不是最好的方法,尽管它确实有效。

因为核心数据实体是 ObservableObjects 我想我应该能够 直接访问和更新绑定(bind)变量,但我找不到任何引用方式 在 ForEach 循环中绑定(bind)到核心数据。

有没有比我下面的代码更合适的方法来做到这一点?

简化示例:

struct DetailView: View {

    var thing: Thing
    var count: Int

    @State var localName: String = ""
    @State private var localComment: String = ""
    @State private var localDate: Date = Date()

    //this does not work - cannot assign String? to State<String>
//    init(t: Thing) {
//        self._localName = t.name
//        self._localComment = t.comment
//        self._localDate = Date()
//    }

    var body: some View {
        //this is the question - is this safe?
        DispatchQueue.main.async {
            self.localName = self.thing.name ?? "no name"
            self.localComment = self.thing.comment ?? "No Comment"
            self.localDate = self.thing.date ?? Date()
        }

        return VStack {
            Text("\(thing.count)")
                .font(.title)
            Text(thing.name ?? "no what?")
            TextField("name", text: $localName)
            Text(thing.comment ?? "no comment?")
            TextField("comment", text: $localComment)
            Text("\(thing.date ?? Date())")
            //TextField("date", text: $localDate)
        }.padding()
    }
}

为了完整起见,ContentView:

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Thing.date, ascending: false)])
    private var things : FetchedResults<Thing>

    @State private var count: Int = 0
    @State private var coverDeletedDetail = false

    var body: some View {
        NavigationView {
            List {
                ForEach(things) { thing in
                    NavigationLink(destination: DetailView(thing: thing, count: self.count + 1)) {
                        HStack {
                            Image(systemName: "gear")
                                .resizable()
                                .frame(width: 40, height: 40)
                                .onTapGesture(count: 1, perform: {
                                    updateThing(thing)
                                })
                            Text(thing.name ?? "untitled")
                            Text("\(thing.count)")
                        }
                    }
                }
                .onDelete(perform: deleteThings)
                if UIDevice.current.userInterfaceIdiom == .pad {
                    NavigationLink(destination: WelcomeView(), isActive: self.$coverDeletedDetail) {
                        Text("")
                    }
                }
            }
            .navigationTitle("Thing List")
            .navigationBarItems(trailing: Button("Add Task") {
                addThing()
            })
        }
    }

    private func updateThing(_ thing: FetchedResults<Thing>.Element) {
        withAnimation {
            thing.name = "Updated Name"
            thing.comment = "Updated Comment"
            saveContext()
        }
    }

    private func deleteThings(offsets: IndexSet) {
        withAnimation {
            offsets.map { things[$0] }.forEach(viewContext.delete)
            saveContext()
            self.coverDeletedDetail = true
        }
    }

    private func addThing() {
        withAnimation {
            let newThing = Thing(context: viewContext)
            newThing.name = "New Thing"
            newThing.comment = "New Comment"
            newThing.date = Date()
            newThing.count = Int64(self.count + 1)
            self.count = self.count + 1
            saveContext()
        }
    }

    func saveContext() {
        do {
            try viewContext.save()
        } catch {
            print(error)
        }
    }
}

和核心数据:

extension Thing {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Thing> {
        return NSFetchRequest<Thing>(entityName: "Thing")
    }
    @NSManaged public var comment: String?
    @NSManaged public var count: Int64
    @NSManaged public var date: Date?
    @NSManaged public var name: String?
}

extension Thing : Identifiable {
}

任何指导将不胜感激。 Xcode 12.2 iOS 14.2

最佳答案

你已经提到了。 CoreData 与 SwiftUI 配合得很好。

只需将您的事物作为 ObservableObject

@ObservedObject var thing: Thing

然后您可以将事物的值作为绑定(bind)传递。这也适用于 ForEach

TextField("name", text: $thing.localName)

关于ios - DetailView 中的 SwiftUI 核心数据绑定(bind)文本字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65225849/

相关文章:

ios - 在iOS中不重复随机数?

iphone - 保存一些 NSManagedObjects 而不是其他的方法?

SwiftUI,NavigationView 在旋转时消失?

macos - SwiftUI MacOS 给出错误 : Undefined symbol: _main

ios - SwiftUI 中的比例高度(或宽度)

ios - 带阴影的 UIView,仅圆顶角和 mask 底边

ios - 简单的Objective C字符串操作

iphone - 将网站保存到 iPhone 上的主屏幕 - 强制名称

ios - 魔法记录在单独的线程中创建/获取实体

ios - Core Data with Swift - 父/子关系