SwiftUI Filtering/Searching 一个二级数​​据模型

SwiftUI Filtering/Searching a Two Level Data Model

我正在尝试使用搜索栏 search/filter 通过 SwiftUI 中的 two-level 数据模型:

struct CategorySection: Identifiable {
    var id = UUID()
    var title: String
    var image: String
    var color: Color
    var paintings: [Painting]
}

struct Painting {
    var title: String
    var size: String
    var year: String
    var text: String
    var show: Bool
} 

let categorySectionData: [CategorySection] = [
    CategorySection(title: "Flowers",
                    image: "Spring",
                    color: Color(#colorLiteral(red: 0.9098039269, green: 0.4784313738, blue: 0.6431372762, alpha: 1)),
                    paintings: [
                        Painting(title: "Spring", size: "70 x 60cm", year: "2001", text: "Spring", show: false),
                        Painting(title: "Flowers", size: "60 x 50cm", year: "2002", text: "The", show: false),
                        Painting(title: "Corn Poppys", size: "70 x 50cm", year: "2005", text: "Year", show: false),
        ]
    ),
    CategorySection(title: "Animals",
                    image: "Deers",
                    color: Color(#colorLiteral(red: 0.2745098174, green: 0.4862745106, blue: 0.1411764771, alpha: 1)),
                    paintings: [
                        Painting(title: "Tigers", size: "70 x 60cm", year: "2001", text: "Spring", show: false),
                        Painting(title: "Deers", size: "60 x 50cm", year: "2002", text: "The", show: false),
                        Painting(title: "Puppies", size: "70 x 50cm", year: "2005", text: "Year", show: false),
        ]
    )
]

主要是objective过滤CategorySection里面的Painting结构体中的title: "Spring"year: "2001"等元素,在CategorySection中显示匹配结果列表中的绘画形式 title,并通过 NavigationLink 传递数据供下一个视图 SearchDetail 在用户点击其中一个时显示。

我尝试了以下搜索第一个元素的方法,但是 Xcode 给了我一堆错误。

let array = locationSectionData[0].paintings[0]
List {
   ForEach(array.filter {[=13=].hasPrefix(searchText) || searchText == ""}, id:\.self) { searchText in
       NavigationLink(destination: SearchDetail(item: searchText)) {
           Text(searchText)
       }
   }
}

然而,上述解决方案适用于像这样的简单数组:

let array = ["Spring", "Deer", "New Year", "Flowers"]

但不适用于 multi-level 数据结构。

理想情况下,搜索结果应该 return Painting 结构的整个实例,例如

Painting(title: "Spring", size: "70 x 60cm", year: "2001", text: "Spring", show: false)

,而不是仅匹配单个元素,如果其中的任何元素与搜索栏输入匹配。

如果有人知道我如何解决这个问题,那就太好了!在这一点上,鉴于当前的数据结构,我什至不确定是否可行。数据结构的修改是可以接受的。

谢谢!

已编辑: 感谢@jtouzy

的帮助,我成功地显示了没有过滤功能的完整绘画标题列表
List {
    ForEach(categorySectionData) { section in
        Section(header: Text(section.title)) {
            ForEach(section.paintings.indices, id: \.self) { painting in
                ForEach(section.paintings[painting].title.filter {[=16=].contains(searchText) || searchText.isEmpty}, id:\.self) { searchText in
                    NavigationLink(destination: SearchDetail(painting: section.paintings[painting])) {
                                        Text(section.paintings[painting].title)
                    }
                }
            }
        }
    }
}

但是,Xcode 在第 ForEach(section.paintings[painting].title.filter {[=26=].contains(searchText) || searchText.isEmpty}, id:\.self) { searchText in 行显示错误 Value of type 'String.Element' (aka 'Character') has no member 'contains'。我知道这可能是因为现在它不是一个数组。

为您解答,

您的 ForEach 函数不是基于字符串而是基于 Painting 对象。

所以你不能在数组项上使用 hasPrefix() 函数。

相反,在 filter 函数中访问您的项目 title :

[=10=].title.hasPrefix(searchText)

你应该遍历你的类别,然后在你的画上,像这样(未启动):

List {
    ForEach(categorySectionData) { section in
        Section(header: Text(section.title)) {
            ForEach(section.paintings) { painting in // Here with your filter
               NavigationLink(destination: SearchDetail(item: painting)) {
                  Text(painting.title)
               }
            }
        }
    }
}

换句话说,

我建议您使用 contains(where:) 而不是 hasPrefix(),以便可以搜索所有单词。

为了让您的代码更简洁,请使用 searchText.isEmpty 而不是 searchText == ""

EDIT 对于已编辑的问题,请参阅我在下面评论中的回复。