Reputation: 185
I need to implement a save button. When a user taps on the button, it has to be filled, by default it's unfilled. But when I run my app some of the buttons in tableView cell are already filled like that
Here's code from TableViewCell
var isFavorite: Bool = false
private let addToFavorites: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(systemName: "heart"), for: .normal)
button.tintColor = UIColor.white.withAlphaComponent(0.85)
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
return button
}()
override func awakeFromNib() {
super.awakeFromNib()
setFavoriteButtonUI()
addToFavorites.addTarget(self, action: #selector(markFavorite), for: .touchUpInside)
}
@objc func markFavorite() {
setFavoriteButtonImage()
}
private func setFavoriteButtonImage() {
isFavorite = !isFavorite
let imgName = isFavorite ? "heart" : "heart.fill"
let favoriteButtonImage = UIImage(systemName: imgName)
self.addToFavorites.setImage(favoriteButtonImage, for: .normal)
}
private func setFavoriteButtonUI() {
addToFavorites.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(addToFavorites)
addToFavorites.topAnchor.constraint(equalTo: filmImgView.topAnchor, constant: 40).isActive = true
addToFavorites.trailingAnchor.constraint(equalTo: filmImgView.trailingAnchor, constant: -20).isActive = true
addToFavorites.heightAnchor.constraint(equalToConstant: 30).isActive = true
addToFavorites.widthAnchor.constraint(equalToConstant: 40).isActive = true
}
In cellForRowAt indexPath method I added
tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.top)
Upvotes: 0
Views: 499
Reputation: 2699
It is a classical problem for iOS beginners.
TableViewCell
has a mechanism of reusing object pool.
When some cell with filled heart slides off the screen, the cell enters the reusing object pool.
The new cell appeared on the screen, maybe is created, or pulled from the reusing object pool.
The simple solution is Mark & Config
.
Just to maintain the cell status data out the scope of cell, we usually have the status data source on the controller.
@objc func markFavorite()
changes the status data source, then table
reload data.
in func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
, config the cell heart status.
in Controller:
var selected = [Int]()
func select(index idx: Int){
selected.append(idx)
table.reloadData()
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
// ...
cell.proxy = self
cell.config(willShow: selected.contains(indexPath.row), idx: indexPath.row)
}
in Cell:
var proxy: XXXProxy? // learn sth proxy yourself
var idx: Int?
func config(willShow toShow: Bool, idx index: Int){
idx = index
btn.isHidden = !toShow
}
// add the rest logic yourself
Upvotes: 1