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

删除具有绑定布尔值的列表项-SwiftUI

如何解决删除具有绑定布尔值的列表项-SwiftUI

在我的应用程序中,我有一个屏幕,用户可以在其中使用Swift applicationId打开和关闭(地图的)过滤器,并删除它们(使用Toggle)。我使用一个Edit Button布尔变量来连接切换开关,以便可以对每个更改做出反应,这是代码

Binding

当我现在使用删除时,出现以下错误//The filter data model class DSFilter{ var filterId : Int var filterTitle : String var isActive : Bool init(filterId : Int,filterTitle : String,isActive : Bool){ self.filterId = filterId self.filterTitle = filterTitle self.isActive = isActive } } //The data model representable struct filterItem : View { @Binding var filter : DSFilter @Binding var isOn : Bool @State var image = Image("defPerson") var body : some View { HStack { image.resizable().frame(width: 45,height: 45).clipShape(Circle()) vstack(alignment: .leading,spacing: 8) { Text(filter.filterTitle).font(Font.custom("Quicksand-Bold",size: 15)) Text(filter.filterTitle).font(Font.custom("Quicksand-Medium",size: 13)).foregroundColor(.gray) }.padding(.leading) Spacer() HStack{ Toggle("",isOn: $isOn).padding(.trailing,5).onReceive([self.isOn].publisher.first()) { (value) in self.filter.isActive = self.isOn }.frame(width: 30) } }.frame(height: 60) .onAppear(){ self.isOn = self.filter.isActive } } } //The view where the user has the control struct FilterView: View { @State var otherFilters : [addedFilter] = [] @Binding var isActive : Bool var body: some View { vstack{ Capsule().fill(Color.black).frame(width: 50,height: 5).padding() ZStack{ HStack{ Spacer() Text("Filters").font(Font.custom("Quicksand-Bold",size: 20)) Spacer() }.padding() HStack{ Spacer() EditButton() }.padding() } List{ ForEach(0..<self.otherFilters.count,id:\.self){ i in filterItem(filter: self.$otherFilters[i].filter,isOn: self.$otherFilters[i].isOn) }.onDelete(perform:removeRows) } Spacer() } } func removeRows(at offsets: IndexSet) { print("deleting") print("deleted filter!") self.otherFilters.remove(at: Array(offsets)[0]) //I use it like so because you can only delete 1 at a time anyway } } //The class I use to bind the isOn value so I can react to change struct addedFilter : Identifiable{ var id : Int var filter : DSFilter var isOn : Bool init(filter : DSFilter){ self.id = Int.random(in: 0...100000) self.filter = filter self.isOn = filter.isActive } } ):

Xcode 12.0

我需要更改什么才能删除项目?对于Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift,line 444 2020-10-06 17:42:12.567235+0300 Hynt[5207:528572] Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift,line 444 的{​​{1}}问题,我应该采取其他方法吗?

解决方法

您好,而不是保留三个不同的数组来管理addFilter,DSFilter和isOn。为什么不尝试以下一个单一模型

class FFilter: Identifiable {
var id: Int
 var addedFilter: addedFilter
var dsFilter: DSFilter
var isOn: Bool

init(addedFilter: addedFilter,dsFilter: DSFilter,isOn: Bool) {
    self.id = addedFilter.id
    self.addedFilter = addedFilter
    self.dsFilter = dsFilter
    self.isOn = isOn
}

}

然后ViewModel更改代码,如下所示:

class ViewModel: ObservableObject {

@Published var superFilters: [FFilter] = [
    FFilter(
        addedFilter: addedFilter(
            filter: DSFilter(filterId: 1,filterTitle: "Title1",isActive: true)
        ),dsFilter: DSFilter(filterId: 1,isActive: true),isOn: true),FFilter(
        addedFilter: addedFilter(
            filter: DSFilter(filterId: 2,filterTitle: "Title2",isActive: false)
        ),dsFilter: DSFilter(filterId: 2,isActive: false),isOn: false),FFilter(
        addedFilter: addedFilter(filter: DSFilter(filterId: 3,filterTitle: "Title3",isActive: true)),dsFilter: DSFilter(filterId: 3,FFilter(
        addedFilter: addedFilter(
            filter: DSFilter(filterId: 4,filterTitle: "Title4",dsFilter: DSFilter(filterId: 4,FFilter(
        addedFilter: addedFilter(
            filter: DSFilter(filterId: 5,filterTitle: "Title5",dsFilter: DSFilter(filterId: 5,isOn: false)
]}

然后更改您的列表代码

  List {
 ForEach(viewModel.superFilters) { filter in
      filterItem(filter: .constant(filter.dsFilter),isOn: .constant(filter.isOn))
      }.onDelete(perform: removeRows(at:)) }

和removeRows方法:

func removeRows(at offsets: IndexSet) {
    print("deleting at \(offsets)")
    self.viewModel.superFilters.remove(atOffsets: offsets)}

我希望它能起作用。让我知道您是否仍然遇到任何问题

,

我建议您将removeRows()函数中的行更改为

self.otherFilters.remove(at: Array(offsets)[0]

self.otherFilters.remove(atOffsets: offsets) 
,

首先,如评论中所述,请使用:

self.otherFilters.remove(atOffsets: offsets) 

第二,遇到问题:问题不在removeRows()函数中。在删除行后再次渲染视图时。当您使用以下代码替换列表视图时,可以确认这一点:

List{
                    
                    ForEach(0..<2,id:\.self){ i in
                        
                        filterItem(filter: self.$otherFilters[i].filter,isOn: self.$otherFilters[i].isOn)
                    }.onDelete(perform:removeRows)
                    
            }
,

因此,经过大量尝试和失败,我找到了答案。 问题似乎出在绑定部分-如果我绑定数组中的元素,编译器将无法处理数组大小的更改,因此我执行了以下操作: 首先,我更改relabel_configs,使filter属性为 - job_name: cadvisor ec2_sd_configs: - region: eu-central-1 port: 28080 filters: - name: tag:aws:autoscaling:groupName values: - data-dev - data-prod relabel_configs: - action: replace source_labels: [__meta_ec2_instance_id] target_label: instance_id - action: replace source_labels: [__meta_ec2_instance_state] target_label: instance_state - action: replace source_labels: [__meta_ec2_instance_type] target_label: instance_type metric_relabel_configs: # Drop series. - action: drop source_labels: [__name__] regex: "(container_tasks_state|container_cpu_load_average_10s)" # Drop all series that do not have a 'name' label. - action: keep source_labels: [name] regex: (.+) # Drop all series that do not have a '/ecs/' c group prefix and a proper # container id after the third forword slash. - action: keep source_labels: [id] regex: ^/ecs/.+/.+ # Drop label 'instance_type'. - action: labeldrop regex: instance_type # Rewrite 'id' label to only include short form container id. - action: replace source_labels: [id] target_label: id regex: ^/ecs/.+/(.{0,12}).* replacement: $1 # Rename label task family. - action: replace source_labels: [container_label_com_amazonaws_ecs_task_definition_family] target_label: task_family - action: labeldrop regex: container_label_com_amazonaws_ecs_task_definition_family # Overwrite 'name' with value of container name label. - action: replace source_labels: [container_label_com_amazonaws_ecs_container_name] target_label: name - action: labeldrop regex: container_label_com_amazonaws_ecs_container_name # namespace - action: replace source_labels: [container_label_promstack_namespace] target_label: namespace - action: labeldrop regex: container_label_promstack_namespace # api_type - action: replace source_labels: [container_label_promstack_api_type] target_label: api_type - action: labeldrop regex: container_label_promstack_api_type 而不是filterItem struct

@State

第二,我将@Binding更改为以下内容:

struct filterItem : View {
    @State var filter : DSFilter
    @Binding var isOn : Bool

然后addedFilter struct循环到以下内容:

struct addedFilter : Identifiable{
    var id : Int
    var isOn : Bool
    
    init(filter : DSFilter){
        self.id = filter.filterId
        self.isOn = filter.isActive
    }
}

在主视图中我添加了:

ForEach

最后是onDelete函数,如下所示:

ForEach(0..<self.normOthFilters.count,id:\.self){ i in
                        filterItem(filter: self.normOthFilters[i],isOn: self.$otherFilters[i].isOn)
                    }.onDelete(perform:removeRows)

总而言之,我不会更改绑定值的值,因此不会收到任何错误!

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