Reputation: 862
I have a tableView
assigned to my ShopViewController
this controller called the ShopCellClass
to draw programmatically each row of the tableView
. The ShopCellClass called my shopClass to know how many item sell.
The problem is in my shopClass I have a UIColor to assign in the background of the cell but the last cell don't have the right color.
I show you the code of my 3 files:
ShopViewController
:
class ShopViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(ShopCellClass.self, forCellReuseIdentifier: "CellShop")
tableView.rowHeight = 155
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return shop.data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"CellShop") as! ShopCellClass
cell.drawTheCard(index: indexPath.row)
return cell
}
}
ShopCellClass
:
class ShopCellClass : UITableViewCell {
var widthOfCard : CGFloat = 0
var heightOfCard : CGFloat = 0
var cardIsDraw : Bool = false
let cardView = UIView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.contentView.addSubview(cardView)
widthOfCard = UIScreen.main.bounds.size.width
heightOfCard = 155
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func drawTheCard(index : Int){
if(cardIsDraw == false){
drawCard(index: index)
cardIsDraw = true
}
}
private func drawCard(index: Int){
cardView.frame = CGRect(x : 0, y : 0, width : widthOfCard, height : heightOfCard)
cardView.backgroundColor = shop.data[index].color
}
}
and ShopClass
:
class ShopClass {
var data: [(id : Int, name : String, price : Double, color : UIColor)] = []
init(){
self.loadShopData()
}
func loadShopData(){
data.append((id : 1, name : "Pack 1", price : 4.99, color : UIColor(rgb: 0xE08B37)))
data.append((id : 2, name : "Pack 2", price : 9.99, color : UIColor(rgb: 0xAFAFAF)))
data.append((id : 3, name : "Pack 3", price : 15.99, color : UIColor(rgb: 0xF3CD00)))
data.append((id : 4, name : "Pack 4", price : 19.99, color : UIColor(rgb: 0xF20000)))
data.append((id : 5, name : "Pack 5", price : 24.99, color : UIColor(rgb: 0x000000)))
}
}
let shop = ShopClass()
the render :
The last color is brown but normally black.
Where did I go wrong?
Upvotes: 0
Views: 224
Reputation: 19792
Quick answer - remove this check from your code:
if(cardIsDraw == false){
Longer answer with explanation:
You assumed that there will be ShopCellClass
class created for each row which is completely wrong.
UITableView
is optimizing drawing by creating only as many Cell classes as absolutely necessary (usually as many as rows visible at once on screen).
When you start scrolling instances that dissapear from the screen (they are moved outside of visible area) are being reused and same instances are used to display new one.
That's why you see new cell being brown - because it's reusing instance of first row - and due to your check for if(cardIsDraw == false){
the code for changing color is not executed.
It's easy to fix in your case - but it's really important to understand that mechanics as lot's of people are getting caught by this keeping also some important parts of their data model in those cells.
You can read more about it here: https://developer.apple.com/documentation/uikit/uitableview/1614878-dequeuereusablecell
Upvotes: 1
Reputation: 100503
Because of dequeuing this var
var cardIsDraw : Bool = false
is changed to true
, so when the last one show it dequeues top brown one where the var is true
so this
if(cardIsDraw == false){
drawCard(index: index)
cardIsDraw = true
}
won't run which cause the color to remain brown and not to change to black , so completely remove the if statement and the var
Upvotes: 1