You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:01:17