swift 使用计算属性基于嵌套数组属性筛选对象数组

a64a0gku  于 2022-11-21  发布在  Swift
关注(0)|答案(2)|浏览(172)

我正在创建一个搜索字段,以允许用户搜索与照片关联的标签,然后只显示My List中包含该标记照片。我使用一个computed属性检查Photo数组是否包含该标记,但这些标记位于Photo对象中几个属性深处的嵌套数组中。我需要一些帮助来从computed属性中过滤照片数组,以便我的列表使用正确的照片。
我正在尝试使用此计算属性来过滤照片:

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
}

使用上面的模型结构,谁能帮我从我的计算属性中过滤出_content的标签?

qacovj5a

qacovj5a1#

当前您返回[TagContent]而不是Bool
filteredPhotos替换为:

var filteredPhotos: [Photo] {
    if searchText.count == 0 {
        return photos
    } else {
        return photos.filter { photo in
            let tagContents = photo.info?.tags.tagContent.filter{ $0._content.contains(searchText) } ?? []
            
            return !tagContents.isEmpty
        }
    }
}
siotufzp

siotufzp2#

为了简化代码并使其更易于阅读,我将在Photo上创建一个计算属性来保存标记

extension Photo {
    var tags: [String] {
        guard let info else { return [] }
        return info.tags.tagContent.map(\._content)
    }
}

然后,用于筛选的计算属性可写为

var filteredPhotos: [Photo] {
    if searchText.count == 0 {
        return photos
    } else {
        return photos.filter { $0.tags.contains(where: { $0.localizedCaseInsensitiveCompare(searchText) == .orderedSame}) }
    }
}

上述过滤将查找完全匹配项,如果要查找包含搜索文本的标记,请使用

return photos.filter { $0.tags.contains(where: { $0.localizedCaseInsensitiveContains(searchText) }) }

相关问题