我有丢失核心数据托管对象中的数据的问题(尽管.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)
}
}
}
}
上面简化了代码,它工作正常。您可以锁定屏幕并返回,并使用有故障的核心数据托管对象重新加载行。
但是只是在 ContactRow(contact:contact) 周围添加 ZStack、VStack 会破坏这个并进入锁屏,然后再次返回会导致该列表重新加载空托管对象(具有 nil 属性)并且列表为空(如果我使用可选的展开contact.name ?? "") 或者如果我使用像contact.name这样的前展开o只会使应用程序崩溃!
所以这打破了
将我的 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)
}
更新
联系人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 案例中有所帮助,但在更复杂的示例中不是所需的解决方案,例如在 .sheet() 中填充托管对象的 List (所以在这里我需要停止展示这样的工作表)
@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()
}
}