在TableViewCell-Swift 5中用userDefaults数组保存多个对象



我正在collectionview单元格中实现Favorite功能。用户应该点击单元格中的收藏夹按钮来保存项目。但是,当点击按钮保存填充单元格的自定义对象中的数据时,只保存一个对象。如果我点击收藏另一个项目,该项目将替换前一个,而不是添加到收藏数组中。想知道我在这里错过了什么。。

这是代码:

自定义对象(Entity.swift(

struct MediaObject: Codable {
let name: String
var results: [Entity]
}
struct Entity: Codable {
var id: Int? 
var name: String? 
var kind: String?
var artwork: String? 
var genre: String? 
var artist: String? 
private enum CodingKeys: String, CodingKey {
case id = "trackId"
case name = "trackName"
case kind = "kind"
case artwork = "artworkUrl100"
case genre = "primaryGenreName"
case artist = "artistName"
}

init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decodeIfPresent(Int.self, forKey: .id)
name = try values.decodeIfPresent(String.self, forKey: .name)
kind = try values.decodeIfPresent(String.self, forKey: .kind)
artwork = try values.decodeIfPresent(String.self, forKey: .artwork)
genre = try values.decodeIfPresent(String.self, forKey: .genre)
artist = try values.decodeIfPresent(String.self, forKey: .artist)
}
}

查看控制器swift

class MediaViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

var obj:MediaObject? = nil {
didSet {
collectionView.reloadData()
}
}

@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var sectionLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = CGSize(width: 100, height: 90)
}
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return obj!.results.count   
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MediaCollectionViewCell
if let obj = obj {
cell.entity = obj.results[indexPath.row]
cell.artistLabel.text = obj.results[indexPath.row].artist
cell.trackLabel.text = obj.results[indexPath.row].name
}
return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 250, height: 205)
}
}

这是我的MediaCollectionViewCell.swift类:

MediaCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var artistLabel: UILabel!
@IBOutlet weak var trackLabel: UILabel!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var favButton: UIButton!
var favoritesArray = [Entity]()
var entity:Entity? = nil {
didSet {
if let entity = entity,
let artworkUrl = NSURL(string: entity.artwork!) {
self.imageView.sd_setImage(with: artworkUrl as URL)
}
}
}

@IBAction func favButtonPressed(_ sender: Any) {
print("isFavorited")
let encoder = JSONEncoder()
if let encoded = try? encoder.encode([entity]) {
let defaults = UserDefaults.standard
defaults.set(encoded, forKey: "entity")
}
let defaultsData = UserDefaults.standard.data(forKey: "entity")
let decoder = JSONDecoder()
let loadedPerson = try? decoder.decode(Entity.self, from: defaultsData!) 
favoritesArray.append(loadedPerson)
print(loadedPerson)
print(loadedPerson?.count)

}

试试这个:

  1. 创建一个检索已保存实体的函数
  2. 如果没有保存的实体,请保存实体数组,即[实体]
  3. 否则将新实体附加到已保存的实体

问题:

您已经在MediaCollectionViewCell中创建了favoritesArray。每次重复使用cell时,favoritesArray都会被重新初始化,即之前添加的entity将丢失。

这就是为什么你总是在里面找到一个entity,以及那个特定的cell

解决方案:

不要在单元格内创建额外的favoritesArray,而是尝试使用closure来保存喜爱的实体。以下是您可以遵循的方法。

1。首先使用class而不是struct,并在Entity模型中添加isFavourite属性,即

class MediaObject: Codable {
let name: String
var results: [Entity]
}
class Entity: Codable {
var id: Int?
var name: String?
var kind: String?
var artwork: String?
var genre: String?
var artist: String?
var isFavourite = false 
enum CodingKeys: String, CodingKey {
case id = "trackId"
case name = "trackName"
case kind = "kind"
case artwork = "artworkUrl100"
case genre = "primaryGenreName"
case artist = "artistName"
}
}

注意:需要在Entity模型中创建init(from:)。在有任何特殊处理时使用。

2.现在,在MediaCollectionViewCell内部创建一个closurefavouriteHandler并在favButtonPressed(_:)内部调用它,即

class MediaCollectionViewCell: UICollectionViewCell {
//rest of the code...
var favouriteHandler: (()->())?
@IBAction func favButtonPressed(_ sender: Any) {
print("isFavorited")
self.favouriteHandler?()
}
}

3.接下来,在collectionView(_:cellForItemAt:)中设置favouriteHandler以更新entityisFavourite状态,然后将所有具有isFavourite = true的实体保存在UserDefaults中。

使用filter(_:)获取所有喜爱的实体。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MediaCollectionViewCell
if let entity = obj?.results[indexPath.row] {
cell.entity = entity
cell.artistLabel.text = entity.artist
cell.trackLabel.text = entity.name
cell.favouriteHandler = {[weak self] in //here...
entity.isFavourite = !entity.isFavourite
let favourites = self?.obj?.results.filter{ $0.isFavourite }
let data = try? JSONEncoder().encode(favourites)
UserDefaults.standard.set(data, forKey: "entity")
}
}
return cell
}

最新更新