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 对于已编辑的问题,请参阅我在下面评论中的回复。
我正在尝试使用搜索栏 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 对于已编辑的问题,请参阅我在下面评论中的回复。