微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从 For Each 循环生成的子视图中删除项目会导致致命错误

如何解决从 For Each 循环生成的子视图中删除项目会导致致命错误

希望你度过一个比我更愉快的夜晚!

所以正如我在标题中提到的,每当我尝试从原始列表中删除一个带有绑定的项目时,我的 for each 循环就会崩溃。我做了一些研究,问题是每个视图都会生成一个带有 id 的视图,但是当您删除子视图中的项目时,它找不到内容并崩溃。返回“线程 1:致命错误:索引超出范围”。我可以通过声明 @State var 而不是 @Binding 来解决这个问题,这确实有效!但是,我的子视图中不止有一个删除按钮,如果我不使用绑定声明,所做的更改不会反映在主视图上。我不想放弃删除按钮和按钮。有没有办法将所有这些都保留在我的子视图中?

主视图声明;

    struct ContentView: View {
    @Observedobject var superReminders = SuperReminders()
    @State var superReminder = SuperReminder()}

我的列表查看;

           List{
                    ForEach(superReminders.reminderlist.indices,id: \.self) { index in
                        NavigationLink(destination: DetailedRemView(superReminder : self.$superReminders.reminderlist[index] ).environmentObject(superReminders)) {
                            squareImageView(superReminder : self.$superReminders.reminderlist[index]).environmentObject(superReminders).environmentObject(superReminders)
                        }.listRowBackground(Color.clear)
                    }.onDelete { indexSet in
                        superReminders.reminderlist.remove(atOffsets: indexSet)}
                }

子视图声明;


import SwiftUI
struct DetailedRemView: View {
    var dateFormatter: DateFormatter {
          let formatter = DateFormatter()
        formatter.dateFormat = "EE,MMM d,YYYY"
          return formatter
      }
    @State public var showingDetail = false
    @Environment(\.colorScheme) var colorScheme: ColorScheme
    @State private var deleteReminderAlert = false
    @EnvironmentObject var superReminders : SuperReminders
    @Environment(\.presentationMode) var presentationMode
    @Binding var superReminder : SuperReminder
    @State private var showDialog = false
    @State var animate = false
    var body: some View {
            vstack{
                HStack(alignment: .center){
                    Text(superReminder.remdate)
                        .font(.title)
                        .multilineTextAlignment(.leading)
                        .padding(.leading)
                        .frame(minWidth: 100,maxWidth: .infinity,maxHeight: 50)
                    Spacer()
                    Button(action: {
                        self.showDialog.toggle()
                    },label: {
                        ZStack{
                            RoundedRectangle(cornerRadius: 10)
                                .fill(Color.blue)
                                .frame(width: 80,height: 35)
                            HStack{
                                Text("Edit")
                                    .foregroundColor(.white)
                                    .multilineTextAlignment(.center)
                                    .cornerRadius(8)
                                Image(systemName: "pencil")
                                    .foregroundColor(.white)
                            }
                        }
                        .shadow(color:Color.gray.opacity(0.3),radius: 3,x: 3,y: 3)
                        .padding(.leading)
                                .alert(isPresented: $showDialog,TextAlert(title: "Edit reminder title",message: "Enter a new title or dissmis.",placeholder: superReminder.remdate,keyboardType: .default) { result in
                                  if let text = result {
                                    if text != "" {
                                        superReminder.remdate = text }
                                    else{}
                                  } else {
                                  }
                                })
                    })
                    .padding(.leading)
                }
                .frame(minWidth: 100,maxWidth: /*@START_MENU_TOKEN@*/.infinity/*@END_MENU_TOKEN@*/,maxHeight: 50,alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                .padding(.vertical,-10)
                ZStack(alignment: .topTrailing){
                    Image(superReminder.image)
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(minWidth: 0,minHeight: 200,maxHeight: .infinity)
                        .saturation(superReminder.pastreminder ? 0.1 : 1)
                        .clipShape(Rectangle())
                            .cornerRadius(10)
                        .padding(.all)
                        .pinchToZoom()
                    HStack{
                        Text(superReminder.dateactual,formatter: dateFormatter)
                            .foregroundColor(.white)
                            .frame(width: 180,height: 30,alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                            .background( superReminder.pastreminder ? Color.gray : Color.lightlygreen)
                            .cornerRadius(8)
                            .animation(/*@START_MENU_TOKEN@*/.easeIn/*@END_MENU_TOKEN@*/)
                        if superReminder.pastreminder == true {
                        ZStack{
                            RoundedRectangle(cornerRadius: 8)
                                .fill(Color.black)
                                .frame(width: 30,height: 30)
                            Image(systemName: "moon.zzz")
                                .foregroundColor(.white)
                        }.offset(x: animate ?  -3 : 0)
                        .onAppear(perform: {
                            shake()
                        })
                        }
                        else{}
                        }
                    .zIndex(0)
                    .offset(x: -10,y: 10)
                    .padding()
                    }
                .zIndex(1)
                .shadow(color: Color.gray.opacity(0.4),x: 1,y: 2)
                HStack{
                    Button(action: {
                        self.showingDetail.toggle()
                    }){
                    ZStack{
                        RoundedRectangle(cornerRadius: 10)
                            .fill(Color.lightlygreen)
                            .frame(width: 140,height: 40)
                        HStack{
                            Text("Reschedule")
                                .foregroundColor(.white)
                                .multilineTextAlignment(.center)
                                .cornerRadius(8)
                            Image(systemName: "calendar")
                                .foregroundColor(.white)
                        }
                    }
                    .shadow(color:Color.gray.opacity(0.3),y: 3)
                    .padding(.all,4.0)
                    }
                        .sheet(isPresented: $showingDetail,content :{
                                remdatepicker(isPresented: self.$showingDetail,superReminder: $superReminder)})
                    Button(action: {
                        if superReminder.pastreminder == true {
                            superReminder.pastreminder = false
                        }
                        else if superReminder.pastreminder == false{
                            superReminder.pastreminder = true
                        }
                    },label: {
                        ZStack{
                            RoundedRectangle(cornerRadius: 10)
                                .fill(superReminder.pastreminder == true ? Color.lightlyblue : Color.gray)
                                .frame(width: 100,height: 40)
                            HStack{
                                Text(superReminder.pastreminder == true ? "Activate" : "Silence")
                                    .foregroundColor(.white)
                                    .multilineTextAlignment(.center)
                                    .cornerRadius(8)
                                Image(systemName: superReminder.pastreminder == true ? "checkmark.circle" : "moon.zzz")
                                    .foregroundColor(.white)
                                    }

                        }
                        .shadow(color:Color.gray.opacity(0.3),y: 3)
                        .padding(.all,4.0)
                    })
                    Button(action: {
                        self.deleteReminderAlert.toggle()
                    },label: {
                        ZStack{
                            RoundedRectangle(cornerRadius: 10)
                                .fill(Color(.red))
                                .frame(width: 40,height: 40)
                            HStack{
                                Image(systemName: "trash")
                                    .foregroundColor(.white)
                            }
                        }
                        .shadow(color:Color.gray.opacity(0.3),4.0)
                        })
                }.padding(.bottom,20)
                .alert(isPresented: $deleteReminderAlert){
                        Alert(
                          title: Text("Are you sure?"),message: Text("Do you want to delete this reminder?"),primaryButton: .destructive(Text("Yes"),action: {
                                superReminders.remove(superReminder: superReminder)
                                self.presentationMode.wrappedValue.dismiss()
                            }),secondaryButton: .cancel(Text("No"))
                )
            }
        }
    }
    func shake()  {
        dispatchQueue.main.asyncAfter(deadline: .Now() + 0.1) {
            withAnimation(Animation.default.repeatCount(6).speed(7)){
                animate.toggle()}}}
}

类和列表;


import SwiftUI

struct SuperReminder: Identifiable,Codable,Equatable {
    var id = UUID()
    var remdate = ""
    var dateactual = Date.init()
    var image  = "New1"
    var pastreminder = false
}

class SuperReminders: ObservableObject {
    @Published var reminderlist: [SuperReminder]
    
    init() {
        self.reminderlist = [
        ]
    }
    func add(superReminder: SuperReminder) {
            reminderlist.append(superReminder)
        }

        func remove(superReminder: SuperReminder) {
            if let index = reminderlist.firstIndex(of: superReminder) {
                reminderlist.remove(at: index)
            }
        }
}

解决方法

这个答案类似于 Accessing and manipulating array item in an EnvironmentObject


superReminders.reminderlist 开始循环遍历 SuperReminder: Identifiable,Codable,Equatable

ForEach(superReminders.reminderlist) { superReminder in
  NavigationLink(destination: DetailedRemView(superReminders: superReminders,superReminder: superReminder)) {
    -----
  }
}

DetailedRemView 中,执行以下操作:

struct DetailedRemView: View {

    @ObservedObject var superReminders : SuperReminders
    
    var superReminder : SuperReminder
    
    // find index of current superReminder   
    var indexOfReminder: Int? {
        superReminders.reminderlist.firstIndex {$0 == superReminder}
    }
    
    var body: some View {
        // Unwrap indexOfReminder
        if let index = indexOfReminder {
            VStack {
               ------ 
            }
        }
    }


    ----

}

在需要更新 superReminder 的任何位置使用 superReminders.reminderlist[index] 中的 DetailRemView

superReminders.reminderlist[index].pastreminder = false

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。