Repardeimaj
Repardeimaj

Reputation: 401

Variables in UICollectionViewCells change to different cells

I have a shop menu for my game in swift. I am using a UICollectionView to hold the views for the items. There is a black glass covering over them before they are bought, and it turns clear when they buy it. I am storing data for owning the certain items in the cells' classes. When I scroll down in the scrollView and then come back up after clicking a cell. A different cell than collected has the clear class and the one I previously selected is black again.

import UIKit

class Shop1CollectionViewCell: UICollectionViewCell {

var owned = Bool(false)
var price = Int()
var texture = String()

@IBOutlet weak var glass: UIImageView!

@IBOutlet weak var ball: UIImageView!

func initiate(texture: String, price: Int){//called to set up the cell

    ball.image = UIImage(named: texture)

    if owned{//change the glass color if it is owned or not
        glass.image = UIImage(named: "glass")
    }else{
        glass.image = UIImage(named: "test")
    }
  }

func clickedOn(){
    owned = true//when selected, change the glass color
    glass.image = UIImage(named: "glass")

   }
}

Then I have the UICollectionView class

import UIKit

class ShopViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

struct ball{
    var price = Int()
    var texture = String()
    var owned = Bool()
}
var balls = Array<ball>()//This is assigned values, just taken off of the code because it is really long

override func viewDidLoad() {
    super.viewDidLoad()
     balls = makeBalls(
}    

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {        
    return (balls.count - 1)
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Shop1CollectionViewCell
    cell.initiate(texture: balls[indexPath.item].texture, price: 1)
    return cell      
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as! Shop1CollectionViewCell
    cell.clickedOn()
    }
}

I am wondering why the variables stored in one class of a cell are being switched to another.

Please ask if you need me to add any additional information or code.

Upvotes: 1

Views: 273

Answers (2)

nkh
nkh

Reputation: 115

You should definitely implement prepareForReuse, and set the cell back to its default state - which in this case would be with the black glass, and unowned.

You can still change the glass in the same way as you're doing in didSelectItemAt, but I'd recommend having the view controller track the state of each ball.

For example, when didSelectItemAt gets called - the view controller would update the ball stored in self.balls[indexPath.row] to have owned = true.

That way, the next time cellForItemAt gets called, you'll know what colour the glass should be by checking the value in self.balls[indexPath.row].owned.

Lastly, you're returning balls.count - 1 in numberOfItems, is this intentional?

In the case where have 10 balls, you're only going to have 9 cells. If you want a cell for each of your objects you should always return the count as is.

Upvotes: 2

E.Coms
E.Coms

Reputation: 11539

Sometimes, you may have to override the following function

override func prepareForReuse(){
  super.prepareForReuse()
 // reset to default value.
}

in class Shop1CollectionViewCell to guarantee cells will behave correctly. Hope you got it.

Upvotes: 1

Related Questions