我从 coredata 中列出了音频项目。删除后,崩溃报告为“EXC_BREAKPOINT (code=1, subcode=0x1b8fb693c)”,为什么?
使用时
ForEach(items, id: \.self)
Run Code Online (Sandbox Code Playgroud)
, 有用。但我的音频具有 id 属性并遵循可识别协议。
更新:我发现添加 if{} 子句可以修复崩溃,但为什么呢?断点在“静态 UUID。unconditionallyBridgeFromObjectiveC ( :) ()”。
struct Test1View: View {
@Environment(\.managedObjectContext) var context
@FetchRequest(fetchRequest: Audio.fetchAllAudios()) var items: FetchedResults<Audio>
var body: some View {
List {
ForEach(items) { item in
if true { // <- this if clause fix crash, but why?
HStack {
Text("\(item.name)")
}
}
}.onDelete(perform: { indexSet in
let index = indexSet.first!
let item = self.items[index]
self.context.delete(item)
try? self.context.save()
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
代码如下:
class Audio: NSManagedObject, Identifiable {
@NSManaged public var id: UUID
@NSManaged public var name: String
@NSManaged public var createAt: Date
}
struct Test1View: View {
@Environment(\.managedObjectContext) var context
var fetchRequest: FetchRequest<Audio> = FetchRequest<Audio>(entity: Audio.entity(), sortDescriptors: [NSSortDescriptor(key: "createAt", ascending: false)])
var items: FetchedResults<Audio> { fetchRequest.wrappedValue }
var body: some View {
List {
ForEach(items) { item in
HStack {
Text("\(item.name)")
}
}.onDelete(perform: { indexSet in
let index = indexSet.first!
let item = self.items[index]
self.context.delete(item)
try? self.context.save()
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
我和你有同样的问题。
使用您自己的id属性来创建它可能是一个坏主意,Identifiable因为 Core Data 将所有属性设置nil为删除对象时,即使您在 Swift CoreData 类中声明它不同。删除您的实体时,该id属性将失效并且 objects.isFault属性设置为true,但 SwiftUIForEach仍保留对此 ID 对象(=您的 UUID)的一些引用,以便能够计算列表的“之前”和“之后”状态并以某种方式尝试访问它,导致崩溃。
因此有以下建议:
ForEach循环中通过检查isFault:if entity.isFault {
EmptyView()
}
else {
// your regular view body
}
Run Code Online (Sandbox Code Playgroud)
id属性为nil,或者通过在您的核心数据模型中将其相应地定义为可选@NSManaged public var id: UUID?
Run Code Online (Sandbox Code Playgroud)
或者不依赖IdentifiableSwiftUIForEach循环中的协议:
ForEach(entities, id: \.self) { entity in ... }
Run Code Online (Sandbox Code Playgroud)
或者
ForEach(entities, id: \.objectID) { entity in ... }
Run Code Online (Sandbox Code Playgroud)
结论:您真的不需要将所有 CoreData 属性都设置为 Swift Optional。循环中id引用的属性优雅地ForEach处理删除(=将其值设置为nil)非常重要。
| 归档时间: |
|
| 查看次数: |
846 次 |
| 最近记录: |