问题描述
在我的应用程序中,我有一个屏幕,用户可以在其中使用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)
总而言之,我不会更改绑定值的值,因此不会收到任何错误!