Xcode 13下为SwiftUI解析CSV生成的ForEach列表添加searchable搜索功能
问题核心
你遇到的类型报错是因为sites是自定义的Site结构体数组,原示例的过滤逻辑是针对String数组设计的,你只需要在过滤时指定要匹配的Site结构体属性(这里你需要匹配站点名称siteName)即可完成适配。
适配后的代码(直接在ForEach内过滤版本)
import SwiftUI import MapKit struct SiteView: View { var sites = loadCSV(from: "csv") @State private var searchText: String = "" var body: some View { NavigationView { List { // 核心修改:对sites数组按搜索词过滤 ForEach(sites.filter { searchText.isEmpty ? true : $0.siteName.localizedCaseInsensitiveContains(searchText) }) { site in let latitude = (site.latNum as NSString).doubleValue let longitude = (site.longNum as NSString).doubleValue // 优化:避免URL强制解包崩溃 if let url = URL(string:"http://maps.apple.com/maps?saddr=&daddr=\(latitude),\(longitude)") { Button(site.siteName, action: { UIApplication.shared.open(url) }) } } } .navigationTitle("Sites") .searchable(text: $searchText) } } } struct SiteView_Previews: PreviewProvider { static var previews: some View { SiteView() } }
可选方案:使用计算属性管理搜索结果
如果你更倾向于把过滤逻辑拆分出去,可以修改你之前尝试的searchResults计算属性,把返回类型改为[Site]即可:
var searchResults: [Site] { if searchText.isEmpty { return sites } else { return sites.filter { $0.siteName.localizedCaseInsensitiveContains(searchText) } } }
之后把ForEach的数据源替换为searchResults即可:
ForEach(searchResults) { site in // 原有单元格逻辑 }
说明
localizedCaseInsensitiveContains是可选用法,作用是搜索时不区分大小写,你也可以替换为普通的contains只做精准大小写匹配- 新增的URL可选绑定是优化项,避免CSV中存在非法坐标时强制解包导致App崩溃
内容的提问来源于stack exchange,提问作者Steve Woodard
相关产品推荐
相关产品推荐

