【问题标题】:How to create sections in a list from an array of a property?如何从属性数组创建列表中的部分?
【发布时间】:2022-01-01 14:17:30
【问题描述】:

大家好,新年快乐,

我在这个网站上学会了创建字典来根据对象的属性准备列表部分,例如:

struct Lieu: Identifiable, Hashable {
    var id = UUID().uuidString
    var nom: String
    var dateAjout = Date()
    var img: String
    var tag: String
    var tag2: String
    var tag3: String
}

以“tag”为关键字准备字典:

private var lieuxParTag: [String: [Lieu]] {
        Dictionary(grouping: listeDeLieux) { lieu in
            lieu.tag
        }
    }
    private var lieuxTags: [String] {
        lieuxParTag.keys.sorted(by: <)
    }

然后在视图中,就很简单了:

ForEach (lieuxTags, id: \ .self) {tag in
                    Section (header: Text (tag)) {
                        ScrollView (.horizontal, showsIndicators: true) {
                            LazyHStack {
                                ForEach (lieuxParTag [tag]!) {Place in
                                    Text (place.name)
                                }
                           }
                      }
                 }

但是如果 "Lieu" 包含这样的标签属性,如何制作部分:

var tags: [String] 

在这张表中,我整合了 “Lieu” 的所有标签,例如:

Lieu(nom: Paris, tags: ["tour eiffel", "bouchons"])

感谢您的帮助。

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    这是一个使用 cmets 的工作示例。我还把你的代码收紧了一点。

    struct SectionsFromArrayView: View {
        
        @State private var listeDeLieux: [Lieu] = Lieu.previewData
        
        private var lieuxParTag: [String: [Lieu]] {
            // This first loop extracts the different tags from the array into a set
            // to unique them so we only iterate each tag once in the next step.
            var tagSet: Set<String> = []
            for lieu in listeDeLieux {
                for tag in lieu.tags {
                    tagSet.insert(tag)
                }
            }
            // This loop puts together the dictionary by filtering listeDeLieux by tag
            var parTag: [String: [Lieu]] = [:]
            for tag in Array(tagSet).sorted() {
                let lieuArray = listeDeLieux.filter( { $0.tags.contains(tag) })
                parTag[tag] = lieuArray
            }
            
            return parTag
        }
        
        var body: some View {
            List {
                // Instead of having a separate computed variable lieuxTags, you can sort the
                // array of the lieuxParTag.keys
                ForEach(lieuxParTag.keys.sorted(by: <), id: \ .self) {tag in
                    Section(header: Text (tag)) {
                        ScrollView(.horizontal, showsIndicators: true) {
                            LazyHStack {
                                ForEach(lieuxParTag[tag]!) { lieu in
                                    Text (lieu.nom)
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    struct Lieu: Identifiable, Hashable {
        var id = UUID().uuidString
        var nom: String
        var dateAjout = Date()
        var img: String
        // By making tags a set, they are uniqued
        var tags: Set<String>
        
        static var previewData: [Lieu] = [
            Lieu(nom: "Alfred", img: "pencil", tags: ["pencil", "doc"]),
            Lieu(nom: "Ben", img: "pencil", tags: ["pencil"]),
            Lieu(nom: "Charles", img: "paperplane", tags: ["paperplane", "doc"]),
            Lieu(nom: "Alfred", img: "paperplane", tags: ["paperplane"]),
            Lieu(nom: "Alfred", img: "pencil", tags: ["pencil", "doc"])
        ]
    }
    

    如果你可以让你的标签成为一个枚举,你可以进一步压缩代码,因为你已经有了你的有限集合。这进一步缩小了 lieuxParTag:

    struct SectionsFromArrayView: View {
        
        @State private var listeDeLieux: [Lieu] = Lieu.previewData
        
        private var lieuxParTag: [Tag: [Lieu]] {
            var parTag: [Tag: [Lieu]] = [:]
            // In order to get an array, Tag.allCases, Tag must conform to CaseIterable
            for tag in Tag.allCases {
                let lieuArray = listeDeLieux.filter( { $0.tags.contains(tag) })
                parTag[tag] = lieuArray
            }
            return parTag
        }
        
        var body: some View {
            List {
                // In order to sort the keys, Tag must conform to Comparable
                ForEach (lieuxParTag.keys.sorted(), id: \ .self) {tag in
                    Section(header: Text(tag.rawValue)) {
                        ScrollView(.horizontal, showsIndicators: true) {
                            LazyHStack {
                                ForEach(lieuxParTag[tag]!) { lieu in
                                    Text(lieu.nom) + Text(Image(systemName: lieu.img))
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    struct Lieu: Identifiable, Hashable {
        var id = UUID().uuidString
        var nom: String
        var dateAjout = Date()
        var img: String
        // By making tags a set, they are uniqued
        var tags: Set<Tag>
        
        static var previewData: [Lieu] = [
            Lieu(nom: "Alfred", img: Tag.pencil.rawValue, tags: [.pencil, .doc]),
            Lieu(nom: "Ben", img: Tag.pencil.rawValue, tags: [.pencil]),
            Lieu(nom: "Charles", img: Tag.paperplane.rawValue, tags: [.paperplane, .doc]),
            Lieu(nom: "Alfred", img: Tag.paperplane.rawValue, tags: [.paperplane]),
            Lieu(nom: "Alfred", img: Tag.pencil.rawValue, tags: [.pencil, .doc])
        ]
    }
    
    enum Tag: String, CaseIterable, Comparable {
        case doc, paperplane, pencil
        
        static func < (lhs: Tag, rhs: Tag) -> Bool {
            lhs.rawValue < rhs.rawValue
        }
    }
    

    【讨论】:

    • 您好,感谢您提供带有注释代码的建议,它完美运行。
    【解决方案2】:

    标准库中没有现成的解决方案,但您可以自己轻松实现。你遍历你的对象,对于每个对象,你遍历它的标签并将当前对象添加到当前标签的字典中:

     var dictionary: [String: [Place]] = [:]
     for place in places {
         for tag in place.tags {
             dictionary[tag, default: []].append(place)
         }
     }
    

    【讨论】:

    • 您好,感谢您的建议,但我无法正确使用它。我收到此错误:“不能在不可变值上使用变异成员:'self' 是不可变的”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 2011-08-22
    • 1970-01-01
    • 2016-11-10
    • 1970-01-01
    • 2014-10-17
    相关资源
    最近更新 更多