Swift中Favorites类实现Soung数组存在性检测函数求助
问题:实现检测Soung对象是否在收藏数组中的函数
我正在编写一个FavoritesNew类,用来对Soung模型的曲目执行添加、删除、保存和加载操作。现在需要实现一个函数来检测某首Soung是否已经加入数组,但尝试多次都失败了。
现有一个仅检测曲目标题的可用示例:
func containsTracks(_ track: Soung) -> Bool { tracks.contains(track.name ?? "aboba") }
我尝试为Soung对象实现相同功能,但遇到了问题:
func containsTrack(_ song: Soung) -> Bool { tracks?.contains(where: <#T##(Soung) throws -> Bool#>) // 不知道这里该写什么 }
希望完成这个函数,使其返回布尔值,用于如下判断逻辑:
if containsTrack == true { removeTrack() } else { addTrack() }
完整类代码如下:
class FavoritesNew: ObservableObject { @Published var tracks: [Soung]? = [] init() { tracks = loadTracks() } // MARK: - TRACKS // 问题在这里 func containsTrack(_ song: Soung) -> Bool { return true } func addTrack(song: Soung) { tracks?.append(song) saveTracks() } func removeTrack(at index: Int) { tracks?.remove(at: index) saveTracks() } func saveTracks() { if let encoded = try? JSONEncoder().encode(tracks) { UserDefaults.standard.set(encoded, forKey: "tracks") } } func loadTracks() -> [Soung] { if let encoded = UserDefaults.standard.data(forKey: "tracks") { if let decoded = try? JSONDecoder().decode([Soung].self, from: encoded) { return decoded } } return [] } }
解决方案
1. 让Soung模型遵循Equatable协议
要直接判断数组中是否包含某个Soung对象,需要让Soung类型遵循Equatable协议,这样Swift才能识别两个Soung实例是否相等。
修改你的Soung模型:
struct Soung: Codable, Equatable { var name: String? // 其他模型属性,比如id、播放时长等 // 自定义相等判断逻辑(可选,编译器会自动生成简单的属性对比逻辑) static func == (lhs: Soung, rhs: Soung) -> Bool { // 推荐用唯一标识(比如id)判断,避免同名曲目误判 return lhs.name == rhs.name // 如果有id字段:return lhs.id == rhs.id } }
2. 修复containsTrack函数
现在可以直接使用数组的contains(_:)方法,同时处理tracks可选的情况:
func containsTrack(_ song: Soung) -> Bool { tracks?.contains(song) ?? false }
tracks?.contains(song):若tracks不为空则检查是否包含目标对象,若tracks为nil则返回nil?? false:当tracks为nil时,默认返回false
3. 额外优化:将tracks改为非可选数组
由于loadTracks()方法默认返回空数组,tracks完全不需要设为可选类型,这样可以省去后续的可选解包操作:
class FavoritesNew: ObservableObject { @Published var tracks: [Soung] = [] init() { tracks = loadTracks() } // ...其他方法不变 func containsTrack(_ song: Soung) -> Bool { tracks.contains(song) } }
备选方案:不遵循Equatable时的写法
如果不想让Soung遵循Equatable,可以用contains(where:)闭包手动指定判断条件:
func containsTrack(_ song: Soung) -> Bool { tracks?.contains(where: { $0.name == song.name }) ?? false // 用id判断的话:$0.id == song.id }
内容的提问来源于stack exchange,提问作者user19727360
相关产品推荐
相关产品推荐

