SwiftUI从列表中删除行

问题描述

enter image description here

从图像中可以看到,我有一个颜色列表,我也希望能够从array中删除颜色。

我尝试添加列表,然后在onDelete上进行ForEach调用,但效果不佳,这给我带来了麻烦。

然后除此以外,我希望列表为所包含元素的大小。

错误:

Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift,line 444

有人可以给我一些建议吗?

代码:

import SwiftUI

struct ContentView: View {
    var cornerRadius: CGFloat = 16
    
    @State public var select = 2
    @State public var bgColors: [Color] =
        [
            Color(red: 21.0/255.0,green: 101.0/255.0,blue: 192.0/255.0),Color(red: 255.0/255.0,green: 193.0/255.0,blue: 7.0/255.0),Color(red: 76.0/255.0,green: 175.0/255.0,blue: 80.0/255.0)
        ]
    @Environment(\.colorScheme) var colorScheme
    
    @State var isShowPicker: Bool = false
    @State var image: Image? = Image("placeholder")
    
    @State private var url: String = "https://a.wattpad.com/useravatar/climaxmite.256.718018.jpg"
    
    init() {
        // Segmented control colors
        UISegmentedControl.appearance().backgroundColor = .systemGray6
        UISegmentedControl.appearance().selectedSegmentTintColor = UIColor(Color.blue)
        UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.systemBackground],for: .selected)
        UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.label],for: .normal)
    }
    
    var body: some View {
        VStack{
            
            ZStack {
                RoundedRectangle(cornerRadius: cornerRadius)
                    .frame(width: UIScreen.main.bounds.width-40,height: 100,alignment: .center)
                    .foregroundColor(colorScheme == .dark ? .black : .white)
                VStack(spacing: 12) {
                    ZStack {
                        Rectangle()
                            .frame(width: UIScreen.main.bounds.width-47,height: 35,alignment: .center)
                            .foregroundColor(Color(UIColor.systemGray6))
                            .cornerRadius(cornerRadius,corners: [.topLeft,.topRight])
                        Text("Select Background")
                            .foregroundColor(Color(UIColor.label))
                            .font(.subheadline)
                            .bold()
                    }
                    Picker(selection: $select,label: Text("Select Background")) {
                        Text("Url").tag(0)
                        Text("Select Image").tag(1)
                        Text("Gradient").tag(2)
                    }.pickerStyle(SegmentedPickerStyle())
                    .padding(EdgeInsets(top: 0,leading: 30,bottom: 0,trailing: 30))
                    Spacer()
                        .frame(height: 3)
                }
            }
            
            if self.select == 0 {
                VStack{
                    ZStack {
                        RoundedRectangle(cornerRadius: cornerRadius)
                            .frame(width: UIScreen.main.bounds.width-40,height: 42,alignment: .center)
                            .foregroundColor(Color(UIColor.systemBackground))
                        TextField("http://",text: $url)
                            .padding(10)
                            .frame(width: UIScreen.main.bounds.width-40)
                            .foregroundColor(Color(UIColor.label))
                            .cornerRadius(cornerRadius)
                            .padding(EdgeInsets(top: 10,leading: 20,bottom: 10,trailing: 10))
                    }
                    
                    Button(action: {
                        
                    },label: {
                        Text("Submit")
                            .foregroundColor(Color(UIColor.systemBackground))
                            .bold()
                    })
                    .padding(EdgeInsets(top: 10,trailing: 20))
                    .foregroundColor(.white)
                    .font(.subheadline)
                    .background(Color.blue)
                    .cornerRadius(cornerRadius)
                }
            }
            
            if self.select == 1 {
                VStack {
                    Button(action: {
                        withAnimation {
                            self.isShowPicker.toggle()
                        }
                    }) {
                        Image(systemName: "photo")
                            .font(.headline)
                            .foregroundColor(colorScheme == .dark ? .white : .black)
                        Text("Import")
                            .font(.headline)
                            .foregroundColor(colorScheme == .dark ? .white : .black)
                        
                    }
                    .foregroundColor(.black)
                }
                .sheet(isPresented: $isShowPicker) {
                    ImagePicker(image: self.$image)
                }
            }
            
            if self.select == 2 {
                VStack(alignment: .trailing){
                    Button(action: {
                        bgColors.append(Color.clear)
                    }) {
                        Image(systemName: "plus")
                            .font(.headline)
                            .foregroundColor(colorScheme == .dark ? .white : .black)
                            .padding(EdgeInsets(top: 10,trailing: 15))
                    }
                    
                    List {
                        
                        ForEach(Array(bgColors.enumerated()),id: \.offset) { index,element in
                            ZStack {
                                ColorPicker("Set the background color",selection: $bgColors[index])
                            }
                            .padding(EdgeInsets(top: 10,trailing: 10))
                        }                .onDelete(perform: delete)
                    }.background(Color.blue)
                    
                }
            }
            
            Spacer()
        }
        .padding(.top,25)
        .ignoresSafeArea(.keyboard)
        .background(Color(UIColor.systemGray6))
        .edgesIgnoringSafeArea(.all)
    }
    
    func delete(at offsets: IndexSet) {
        bgColors.remove(atOffsets: offsets)
    }
}

struct RoundedCorner: Shape {
    var radius: CGFloat = .infinity
    var corners: UIRectCorner = .allCorners
    
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect,byRoundingCorners: corners,cornerRadii: CGSize(width: radius,height: radius))
        return Path(path.cgPath)
    }
}

extension View {
    func cornerRadius(_ radius: CGFloat,corners: UIRectCorner) -> some View {
        clipShape( RoundedCorner(radius: radius,corners: corners) )
    }
}

// extension for keyboard to dismiss
extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder),to: nil,from: nil,for: nil)
    }
}

struct ImagePicker: UIViewControllerRepresentable {
    
    @Environment(\.presentationMode)
    var presentationMode
    
    @Binding var image: Image?
    
    class Coordinator: NSObject,UINavigationControllerDelegate,UIImagePickerControllerDelegate {
        
        @Binding var presentationMode: PresentationMode
        @Binding var image: Image?
        
        init(presentationMode: Binding<PresentationMode>,image: Binding<Image?>) {
            _presentationMode = presentationMode
            _image = image
        }
        
        func imagePickerController(_ picker: UIImagePickerController,didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
            image = Image(uiImage: uiImage)
            presentationMode.dismiss()
            
        }
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            presentationMode.dismiss()
        }
        
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(presentationMode: presentationMode,image: $image)
    }
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        return picker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController,context: UIViewControllerRepresentableContext<ImagePicker>) {
        
    }
    
}

解决方法

问题在于,在您的List中,给您的id\.offset。但是,由于您要从bgColors中删除数据,因此该数据可以更改。相反,您应该将id设置为\.element,因为每种颜色都将保持不变。

请考虑以下简化示例,当您从列表中删除Color时,该示例将崩溃:

struct ContentView: View {
    
    @State private var arr: [Color] = [.red,.green,.blue]

    var body: some View {
        List {
            ForEach(Array(arr.enumerated()),id: \.offset) { (index,_) in
                ColorPicker("Color",selection: $arr[index])
            }
            .onDelete(perform: delete)
        }
    }
    
    private func delete(at offsets: IndexSet) {
        arr.remove(atOffsets: offsets)
    }
}

还有一个工作示例,其中的变化是为id赋予了List,而颜色是新的Binding

struct ContentView: View {

    @State private var arr: [Color] = [.red,id: \.element) { (index,_) in
                ColorPicker(
                    "Color",selection: Binding<Color>(
                        get: { arr[index] },set: { arr[index] = $0 }
                    )
                )
            }
            .onDelete(perform: delete)
        }
    }

    private func delete(at offsets: IndexSet) {
        arr.remove(atOffsets: offsets)
    }
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...