SwiftUI中如何用计算属性基于嵌套数组过滤Photo对象
SwiftUI搜索框筛选嵌套标签的照片列表
需求是实现一个搜索框,根据照片关联的标签(TagContent的_content字段)筛选照片列表,仅显示包含该标签的照片。
原尝试的计算属性代码:
struct PhotoListView: View { let photos: [Photo] @State private var searchText: String = "" var filteredPhotos: [Photo] { if searchText.count == 0 { return photos } else { return photos.filter { photo in return photo.info?.tags.tagContent.filter { $0._content.contains(searchText) } } } } var body: some View { NavigationStack { List { ForEach(filteredPhotos) { photo in NavigationLink { PhotoDetailView(photo: photo) } label: { PhotoRow(photo: photo) } } } .navigationTitle("Recent Photos") .searchable(text: $searchText) } } }
报错信息:Cannot convert value of type '[TagContent]?' to closure result type 'Bool'
数据模型结构:
class Photo: Decodable, Identifiable { let id: String let owner: String let secret: String let title: String let server: String let farm: Int var imageURL: URL? var info: PhotoInfo? } struct PhotoInfo: Decodable { let id: String let dateuploaded: String let tags: PhotoTags } struct PhotoTags: Decodable { let tagContent: [TagContent] enum CodingKeys: String, CodingKey { case tagContent = "tag" } } struct TagContent: Decodable, Hashable { let id: String let _content: String }
问题原因
photos.filter的闭包要求返回Bool类型,但当前代码返回的是[TagContent]?(因photo.info是可选值,链式调用后结果为可选数组)。filter方法是筛选符合条件的元素组成新数组,而我们需要的是判断是否存在符合条件的标签,应该使用contains方法。
修正后的代码
修改filteredPhotos计算属性,用contains替代filter,同时处理可选链的空值情况:
var filteredPhotos: [Photo] { guard !searchText.isEmpty else { return photos } return photos.filter { photo in photo.info?.tags.tagContent.contains { tag in tag._content.localizedCaseInsensitiveContains(searchText) } ?? false } }
补充说明
- 用
guard !searchText.isEmpty替代searchText.count == 0,更贴合Swift代码风格; contains闭包返回Bool,用于判断当前标签的_content是否匹配搜索文本;- 使用
localizedCaseInsensitiveContains实现忽略大小写的搜索,优化用户体验; - 可选链末尾添加
?? false,确保当photo.info为nil时,该照片不会被纳入筛选结果。
内容的提问来源于stack exchange,提问作者jbeu425
相关产品推荐
相关产品推荐

