如何将CollectionView单元格添加至收藏CollectionView?模型favorite属性无效
实现收藏功能的解决方案
1. 修正数据模型
你的favorite属性位置错误,应该放在Results结构体中(每个电影条目需要独立的收藏状态),同时设为可变属性并赋予默认值(API返回数据不包含该字段):
// MARK: - Results struct Results: Codable { // 保留原有所有属性... var favorite: Bool = false // 移至此处,设为可变并默认未收藏 // 自定义解码键,忽略favorite(API不返回该字段) enum CodingKeys: String, CodingKey { case wrapperType, kind, collectionID = "collectionId", trackID = "trackId" case artistName, collectionName, trackName, collectionCensoredName case trackCensoredName, collectionArtistID, collectionArtistViewURL case collectionViewURL, trackViewURL, previewURL, artworkUrl30 case artworkUrl60, artworkUrl100, collectionPrice, trackPrice case trackRentalPrice, collectionHDPrice, trackHDPrice, trackHDRentalPrice case releaseDate, collectionExplicitness, trackExplicitness case discCount, discNumber, trackCount, trackNumber, trackTimeMillis case country, currency, primaryGenreName, contentAdvisoryRating case longDescription, hasITunesExtras, shortDescription, artistID, artistViewURL } }
2. 给自定义单元格添加回调机制
单元格不应直接处理数据逻辑,通过闭包将按钮点击事件传递给ViewController,同时根据数据状态更新按钮UI:
class CustomCollectionViewCell: UICollectionViewCell { // 保留原有控件定义... // 添加数据绑定属性和回调闭包 var result: Results? { didSet { updateFavoriteButtonStatus() } } var onFavoriteTap: (() -> Void)? override init(frame: CGRect) { super.init(frame: frame) // 原有初始化代码不变... } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @objc func likeTapped() { onFavoriteTap?() // 触发回调通知ViewController } // 根据数据状态更新按钮图标 private func updateFavoriteButtonStatus() { let iconName = result?.favorite ?? false ? "redheart" : "heart" likeButton.setImage(UIImage(named: iconName), for: .normal) } }
3. 在ViewController中处理收藏逻辑
维护收藏数组,处理按钮点击后的状态切换,并刷新对应UI:
class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { let networkService = NetworkService() var movie: Movie? = nil var favoriteMovies: [Results] = [] // 收藏列表数组 // 原有CollectionView定义不变... func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "identifier", for: indexPath) as! CustomCollectionViewCell cell.contentView.layer.cornerRadius = 15 guard let currentResult = movie?.results?[indexPath.row] else { return cell } // 绑定数据到单元格 cell.result = currentResult cell.imageView.downloaded(from: currentResult.artworkUrl100 ?? "") // 设置收藏按钮回调 cell.onFavoriteTap = { [weak self] in guard let self = self else { return } // 切换当前条目的收藏状态 self.movie?.results?[indexPath.row].favorite.toggle() // 更新收藏数组 if let updatedResult = self.movie?.results?[indexPath.row] { if updatedResult.favorite { self.favoriteMovies.append(updatedResult) } else { // 通过唯一标识trackID移除已取消收藏的条目 self.favoriteMovies.removeAll { $0.trackID == updatedResult.trackID } } } // 刷新当前单元格 collectionView.reloadItems(at: [indexPath]) // 刷新收藏CollectionView(替换为你的收藏列表CollectionView实例) // self.favoritesCollectionView.reloadData() } return cell } // 保留原有其他方法不变... }
关键注意事项
- 避免用Tag管理状态:单元格复用会导致Tag状态混乱,必须通过数据模型的状态驱动UI更新。
- 弱引用避免内存泄漏:在闭包中使用
[weak self]防止ViewController被单元格强引用导致内存泄漏。 - 收藏列表唯一性:使用
trackID(或其他唯一标识)判断是否已收藏,避免重复添加。
内容的提问来源于stack exchange,提问作者Demis Kobylkov
相关产品推荐
相关产品推荐

