SwiftUI中基于Model实现列表搜索的方法求助
解决SwiftUI List结合外部Model的搜索功能问题
核心思路
你的需求是基于外部定义的FavoriteModel和FavoriteElements实现分组列表的搜索,关键是要过滤分组内的元素,并只保留包含匹配元素的分组,同时处理搜索文本为空时显示全部内容的场景。
修改后的完整代码
ContentView.swift
import SwiftUI struct ContentView: View { @State private var searchText: String = "" // 计算属性:根据搜索文本动态过滤数据 private var filteredFavorites: [FavoriteModel] { guard !searchText.isEmpty else { return myFavorites // 搜索文本为空时返回全部数据 } // 转换为小写,实现不区分大小写的搜索 let lowercasedSearch = searchText.lowercased() // 过滤每个分组:只保留包含匹配元素的分组 return myFavorites.map { model in let filteredElements = model.elements.filter { $0.name.lowercased().contains(lowercasedSearch) } return FavoriteModel(id: model.id, title: model.title, elements: filteredElements) }.filter { !$0.elements.isEmpty } // 移除没有匹配元素的空分组 } var body: some View { NavigationView { List { // 遍历过滤后的分组数据 ForEach(filteredFavorites) { favorite in Section(header: Text(favorite.title)) { ForEach(favorite.elements) { element in NavigationLink(destination: DetailsView(chosenFavoriteElement: element)) { Text(element.name) } } } } } .navigationBarTitle("Favorite Book App") .navigationBarTitleDisplayMode(.inline) .searchable(text: $searchText) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
FavoriteModel.swift(无需修改)
import Foundation struct FavoriteModel : Identifiable { var id = UUID() var title : String var elements : [FavoriteElements] } struct FavoriteElements : Identifiable { var id = UUID() var name : String var imageName : String var description : String } let macOS = FavoriteElements(name: "MacOS", imageName: "macosventura", description: "MacOS 13 Ventura") let windows = FavoriteElements(name: "Windows", imageName: "windows11", description: "Windows 11") let borusanMannesmann = FavoriteElements(name: "Borusan Mannesmann", imageName: "borusanlogo", description: "Borusan Mannesmann Boru A.Ş.") let aselsan = FavoriteElements(name: "Aselsan", imageName: "aselsan", description: "Aselsan Askeri Sanayi") let favoriteOperatingSystems = FavoriteModel(title: "Favorite Operating Systems", elements: [macOS, windows]) let favoriteCompanies = FavoriteModel(title: "Favorite Companies", elements: [borusanMannesmann, aselsan]) let myFavorites = [favoriteOperatingSystems, favoriteCompanies]
关键修改点说明
- 替换状态变量为计算属性:用
filteredFavorites计算属性替代原有的filteredText,无需手动监听searchText变化,SwiftUI会自动在searchText更新时重新计算过滤结果。 - 不区分大小写的搜索:将搜索文本和元素名称都转换为小写,确保搜索结果不受大小写影响。
- 过滤逻辑分层:
- 先过滤每个分组内的
elements,只保留名称包含搜索文本的元素; - 再过滤整个分组列表,移除没有匹配元素的空分组,避免显示空的Section。
- 先过滤每个分组内的
- 保持原有分组结构:通过映射原
FavoriteModel生成新的过滤后模型,保留原有分组的标题和ID,确保Section的展示逻辑和原代码一致。
内容的提问来源于stack exchange,提问作者caneraltuner
相关产品推荐
相关产品推荐

