У меня проблема с потерей данных в управляемых объектах Core Data (все свойства, несмотря на .objectID) становятся нулевыми после перехода на экран блокировки и обратно.
Я отлаживал это и нашел такую проблему.
struct SimpleContactsList: View {
@FetchRequest var contacts: FetchedResults<Contact>
let companyId: String
init(companyId: String) {
self.companyId = companyId
self._contacts = FetchRequest(
entity: Contact.entity(),
sortDescriptors: [
NSSortDescriptor(key: "name", ascending: true, selector: #selector(NSString.caseInsensitiveCompare(_:))),
NSSortDescriptor(keyPath: \Contact.createdAt, ascending: true)
],
predicate: NSPredicate(format: "company.id == %@", companyId)
)
}
var body: some View {
List {
ForEach(Array(self.contacts.enumerated()), id: \.1.objectID) { (i, contact) in
ContactRow(contact: contact)
}
}
}
}
Имея вышеприведенный код упрощает код, он работает нормально. Вы можете go заблокировать экран и go назад, и строки будут перезагружены с ошибками управляемых объектов данных ядра.
Но простое добавление ZStack, VStack вокруг ContactRow (contact: contact) разрывает это и работает lockscreen, а затем снова вызывает, что список перезагружается с пустыми управляемыми объектами (со свойствами nil) и список пуст (если я используя необязательное развертывание contact.name ?? "") или просто вылетает приложение, если я использую перед развертыванием o как contact.name!
Так что это нарушает
Изменение моих SimpleContactLists на это нарушает код как добавление ZStack предотвращает обновление элементов списка из базы данных?
List {
ForEach(Array(self.contacts.enumerated()), id: \.1.objectID) { (i, contact) in
ZStack {
ContactRow(contact: contact)
}
.listRowBackground( (i%2 == 0) ? Color("DarkRowBackground") : .white)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
.onDelete(perform: self.delete)
}
UPDATE
contact NSManagedObject пуст, но ссылается на self.contacts [i] НЕТ! Почему?
List {
ForEach(Array(self.contacts.enumerated()), id: \.1.objectID) { (i, contact) in
Button(action: {
self.selectedId = self.contacts[i].id!
self.showDetails = true
}) {
Contact(contact: contact)
//ContactRow(contact: self.contacts[i])
.background(Color.white.opacity(0.01))
}
.buttonStyle(ListButtonStyle())
.listRowBackground( (i%2 == 0) ? Color("DarkRowBackground") : .white)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
.onDelete(perform: self.delete)
}
ОБНОВЛЕНИЕ 2
У меня есть такое решение. Это помогает в некоторых случаях List-from-FetchResults, но не является желательным решением в более сложных примерах, таких как List, заполненный управляемыми объектами в .sheet () (поэтому здесь мне нужно прекратить представлять такой лист)
@State var theId = UUID()
List {
//rows
}
.id(theId)
.onReceive(appBecomeActivePublisher, perform: { _ in
self.theId = UUID()
}
extension UIApplication {
static var didBecomeActivePublisher: AnyPublisher<UIKit.Notification, Never> {
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
.eraseToAnyPublisher()
}
}