Невозможно обновить sh пользовательский интерфейс, если обновление в ItemView - PullRequest
1 голос
/ 27 февраля 2020

Работает нормально, если я просто помещаю код ItemView в ForEach, трогаю имя элемента списка, переключаю проверку атрибута, цвет имени меняется. Когда я извлекаю код в ItemView, данные изменяются, но пользовательский интерфейс не обновляется, почему?

замечают, что Item является классом, а не структурой. Может быть, это важно.

import CoreData
class Item: NSManagedObject, Identifiable {
    @NSManaged public var createAt: Date?
    @NSManaged public var id: UUID?
    @NSManaged public var name: String?
    @NSManaged public var check: Bool
    ...
}

struct ContentView: View {
    @Environment(\.managedObjectContext) var context
    @FetchRequest(entity: Item.entity(), sortDescriptors: [NSSortDescriptor(key: "createAt", ascending: false)]) var items: FetchedResults<Item>

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(items) { item in
//                        HStack {
//                            Text("\(item.name!)").foregroundColor(item.check ? .red : .gray)
//                            Spacer()
//                        }.onTapGesture {
//                            item.check.toggle()
//                            try? self.context.save()
//                        }
                        ItemView(item: item)
                    }.onDelete(perform: { indexSet in
                        let index = indexSet.first!
                        let item = self.items[index]
                        self.context.delete(item)
                        try? self.context.save()
                    })
                }
                Button(action: {
                    let item = Item(context: self.context)
                    item.id = UUID()
                    item.createAt = Date()
                    item.name = "New Item"
                    try? self.context.save()
                }) {
                    Text("New")
                }
            }
        }
    }
}

struct ItemView: View {
    @Environment(\.managedObjectContext) var context
    var item: Item

    var body: some View {
        HStack {
            Text("\(item.name!)").foregroundColor(item.check ? .red : .gray)
            Spacer()
        }.onTapGesture {
            self.item.check.toggle()
            try? self.context.save()
        }
    }
}

1 Ответ

2 голосов
/ 27 февраля 2020

Это потому, что ItemView по умолчанию определено как равное, потому что свойство item является указателем.

Вот что можно сделать (снимок не проверяется), поэтому просто поцарапано (но должно опыт работы):

1) измените ForEach следующим образом

ForEach(items) { item in
    ItemView(item: item).equatable()

2) [!!!] убедитесь, что ваш Item также Equatable с учетом изменений check свойство

3) сделать ItemView равным

struct ItemView: View, Equatable {
    static func == (lhs: ItemView, rhs: ItemView) -> Bool {
        return lhs.item == rhs.item // preferable, but can be other appropriate
    }
    ...

Обновление: альтернативный способ

struct ItemView: View {
    @Environment(\.managedObjectContext) var context
    var item: Item

    @State private var refresh: Bool = true
    var body: some View {
        HStack {
            Text("\(item.name!)").foregroundColor(item.check ? .red : .gray)
                .background(Color.clear.opacity(self.refresh ? 1.0 : 0.0)) // just to be in view body
            Spacer()
        }.onTapGesture {
            self.item.check.toggle()
            try? self.context.save()
            self.refresh.toggle() // force refresh self
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...