致命错误:索引超出范围,同时在 SwiftUI 的列表中从 Firebase 中删除项目
Posted
技术标签:
【中文标题】致命错误:索引超出范围,同时在 SwiftUI 的列表中从 Firebase 中删除项目【英文标题】:Fatal error: Index out of range, while deleting item from Firebase inside a List in SwiftUI 【发布时间】:2020-12-10 12:34:35 【问题描述】:我已经尝试过这里和其他地方提出的各种解决方案(例如,向 Collection 添加扩展、[安全] 元素迭代等),但遗憾的是没有任何效果。我也试过改变“最后!” “第一!”在 onDelete 代码中,但这会导致同样的问题,尽管令人惊讶的是它确实适用于我见过的其他线程中的其他人。我应该注意到,这只是在我将 CoreData 与 Firebase 结合到我的应用程序中之后才开始发生的......您的帮助将不胜感激。提前致谢。
用作环境对象并启动 Firebase 的类:
class DayData: ObservableObject, Identifiable
@Published var date = Date()
@Published var completed = false
@Published var percentage: Double = 0.0
@Published var liquids: Double = 0
var allData : [DayCellModel] = []
let dbRef = Firestore.firestore()
init()
readAllData()
func readAllData()
dbRef.collection("keanu").addSnapshotListener (snap, err) in
guard let docs = snap else return
self.allData = docs.documents.compactMap( (doc) -> DayCellModel? in
return try! doc.data(as: DayCellModel.self)
)
DayCellModel 结构仅用于 Firebase:
struct DayCellModel : Identifiable, Codable
@DocumentID var id: String?
var date : Date = Date()
var completed : Bool = false
var percentage : Double = 0.0
var liquids: Int = 0
仅用于CoreData的数据模型类:
extension NSDayData
@nonobjc public class func getDayData() -> NSFetchRequest<NSDayData>
let request:NSFetchRequest<NSDayData> = NSDayData.fetchRequest() as! NSFetchRequest<NSDayData>
let sortDescriptor = NSSortDescriptor(key: "date", ascending: true)
request.sortDescriptors = [sortDescriptor]
return request
@NSManaged public var completed: Bool
@NSManaged public var id: UUID?
@NSManaged public var liquids: Double
@NSManaged public var percentage: Double
@NSManaged public var date: Date?
extension NSDayData : Identifiable
包含代码到我的 List 和 onDelete 代码的结构:
struct ListView: View
@Environment(\.managedObjectContext) var moc
@FetchRequest(fetchRequest : NSDayData.getDayData()) var dayItems:FetchedResults<NSDayData>
@EnvironmentObject var data : DayData
var body: some View
NavigationView
VStack(spacing: 10)
HStack
Text("Date")
Text("Completion")
Text("Liquids")
.font(.caption)
List
ForEach(dayItems, id: \.id) collection in
HStack
Text("\(collection.date?.string(format: self.dateFormat) ?? Date().string(format: self.dateFormat))")
Text(collection.percentage > 0.95 ? "100%" : "\(Int(collection.percentage * 100))")
Text("\(Int(collection.liquids))oz")
.font(.system(size: 10, weight: .light))
.onDelete (index) in
let db = Firestore.firestore()
db.collection("keanu")
.document(self.data.allData[index.last!].id!)
.delete (err) in
if err != nil
print((err?.localizedDescription)!)
return
self.deleteItems(at: index)
func deleteItems(at offsets: IndexSet)
withAnimation
offsets.map dayItems[$0] .forEach(moc.delete)
saveMoc()
data.allData.remove(atOffsets: offsets)
我有另一个视图,我在其中添加新数据并将其保存到 Firebase 和 CoreData,如下所示:
if self.newCollection
let dayData = NSDayData(context: self.moc)
dayData.id = UUID()
dayData.date = self.data.date
dayData.completed = self.data.percentage > 0.95
dayData.percentage = self.data.percentage
dayData.liquids = self.data.liquids
do
try moc.save()
catch
let error = error as NSError
fatalError("Unresolved Error: \(error)")
let db = Firestore.firestore()
db.collection("keanu").document()
.setData(
[
"date": self.data.date,
"completed": self.data.percentage > 0.95,
"percentage": self.data.percentage,
"liquids": self.data.liquids
]) (err) in
if err != nil
print((err?.localizedDescription)!)
return
【问题讨论】:
【参考方案1】:好吧,在 youtube 上观看了 kavsoft 的一些精彩视频后,我终于明白了。对于那些可能遇到类似问题的人,这是我的解决方案:
不要在 ForEach 上使用 onDelete 函数。而是创建一个按钮来删除项目,这样您就不必处理索引。
如果使用 CoreData 和 Firebase,请创建一个字符串变量,该变量将等效于结构和核心数据类(见下文)。
在编辑视图(添加新视图等)中,我创建了以下内容:
@Binding var docID: 字符串
在列表视图中,为 docID 的绑定变量创建一个 @State
@State var docID = ""
然后,当我从列表中显示编辑视图时,它的内容如下:
.sheet(isPresented: $show, content:
EditView(docID: $docID, show: self.$show newEntry: true)
.environment(\.managedObjectContext, self.moc)
)
我添加了一个按钮,可以同时从 Firebase、CoreData 和列表中删除条目。它嵌套在 ForEach 中,因此您会在列表中的每个项目旁边获得一个“减号”符号:
if self.remove
VStack
Button(action:
let db = Firestore.firestore()
db.collection("myCollection").document(docID).delete()
moc.delete(collection)
saveMoc()
)
Image(systemName: "minus.circle.fill")
.buttonStyle(BorderlessButtonStyle())
5.2。我还有一个导航栏按钮,触发“-”符号出现
var deleteButton : some View
Button(action:
self.remove.toggle()
)
Image(systemName: self.remove ? "xmark.circle" :
"trash")
最后,保存我设置的条目时 CoreData 属性:
let dayData = NSDayData(context: self.moc)
dayData.id = self.docID
Firebase 属性:
let db = Firestore.firestore()
db.collection("yourCollection").document(self.docID)
.setData(
[
"id": self.docID,
...
【讨论】:
以上是关于致命错误:索引超出范围,同时在 SwiftUI 的列表中从 Firebase 中删除项目的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI .onDelete 抛出致命错误:索引超出范围
SwiftUI - 致命错误:从数组中删除元素时索引超出范围