分段选择器视图选择具有相同索引的部分中的所有行

Posted

技术标签:

【中文标题】分段选择器视图选择具有相同索引的部分中的所有行【英文标题】:sectioned pickerview chooses all rows in sections with same index 【发布时间】:2020-12-30 12:18:02 【问题描述】:

我正在尝试创建一个包含部分的PickerView

每个项目都符合“id”,我用项目的 id 标记Text(这是唯一的,我验证没有冲突)

PickerView 似乎忽略了我分配的标签,并为每个部分选择具有相同对应索引的所有行

我还尝试使用随机 UUID 标记每个项目以检查行为,它似乎继续

struct ExperimentPickerView: View 
    @StateObject var localExperiment = RunningExperiment.active
    @StateObject var experiments = RemoteExperiments.instance
    @State var picked : Int = -1
    var body: some View 
        Picker("active", selection: $picked) 
            ForEach(Array(experiments.experiments.enumerated()), id: \.offset)  i,experiment in
                Section(header: Text("\(experiment.name)")) 
                    ForEach(Array(experiment.variations.enumerated()), id: \.offset)  j,variation in
//                        Text("\(variation.name) \(variation.id)").tag(variation.id)
                        Text("\(variation.name) \(variation.id)").tag(UUID().description)
                        
                    
                
            
        .id(picked).onReceive([self.picked].publisher.first())  (value) in
            print(value) // prints the row number and not the id of the element
            
        
    



struct Experiment : Codable, Equatable, Identifiable 
    var id: Int 
        var hasher = Hasher()
        name.hash(into: &hasher)
        variations.hash(into: &hasher)
        return hasher.finalize()
    
    let name : String
    let variations: [Variation]
    enum CodingKeys: String, CodingKey 
        case name
        case variations
    
    
    init(from decoder: Decoder) throws 
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let n = try container.decode(String.self, forKey: .name)
        name = n
        let a = try container.decode(AnyCodable.self, forKey: .variations)
        print(a)
        let b = a.value as! [[String:Any]]
        var vars = [Variation]()
        for v in b 
            if let na = v["name"], let nna = na as? String 
                vars.append(Variation(name: nna, experiment: n))
            
        
        variations = vars
        
        
    


struct Variation: Codable, Equatable, Identifiable, Hashable 
    var id: Int 
        var hasher = Hasher()
        name.hash(into: &hasher)
        experiment.hash(into: &hasher)
        let hashValue = hasher.finalize()
        return hashValue
    
    
    let name: String
    var experiment: String
    
    enum CodingKeys: String, CodingKey 
        case name, experiment
    

【问题讨论】:

【参考方案1】:

tag 应该与selection 类型相同,因为它用于匹配选取的行。并且id 在这种情况下不应该被修改,因为它会完全重新初始化选择器。

提供的代码不可测试,因此这里只是一个解决方案演示(您的场景的简化复制)。

使用 Xcode 12.1 / ios 14.1 测试。

struct Pair: Hashable 
    var section = ""
    var row = -1


struct ExperimentPickerView: View 
    var sections = ["A", "B", "C"]
    var rows = Array(0..<5)

    @State private var picked = Pair(section: "B", row: 2) // << here !! (initialised demo)

    var body: some View 
        Picker("active", selection: $picked) 
            ForEach(sections, id: \.self)  section in
                Section(header: Text("\(section)").bold()) 
                    ForEach(rows, id: \.self)  i in
                        Text("\(section) \(i)")
                           .tag(Pair(section: section, row: i))   // << match !!
                    
                
            
        .onReceive([self.picked].publisher.first())  (value) in
            print(value)
        
    

【讨论】:

它们都是 int 类型且哈希值不变 UUID 只是测试它的行为方式。但是使用“variation.id”会产生一个唯一的 Int,它也与“picked”的类型相同 我将它修改为从 \.offset 开始工作,它开始工作了?‍♂️

以上是关于分段选择器视图选择具有相同索引的部分中的所有行的主要内容,如果未能解决你的问题,请参考以下文章

无法在 swift ui 中单击分段选择器

分段的 tableview 索引选择突出显示

带有选取器(分段控件)子视图和选择手势的列表项

选择具有相同列的所有行以分隔mysql中的列

具有彩色背景和波纹效果的列表视图选择器

如何分解包含选择器的函数?