Variables in UICollectionViewCells change to different cells

Repa

New Member
#1
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.
Mã:
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
Mã:
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.
 

Admin

Administrator
Thành viên BQT
#2
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.
 
OP
OP
R

Repa

New Member
#3
This still does not work. This does not change anything. I want for each cell to be automatically clear glass if it is already owned. Is there anything else I can do?
 

Admin

Administrator
Thành viên BQT
#4
Where are you setting the colour of the glass now? If you do self.balls[indexPath.row].owned = trueinside didSelectItemAt, and then inside cellForItemAt do cell.glass.image = UIImage(named: "glass") when self.balls[indexPath.row].owned = true then you should see the correct behaviour.

Also, don't set the image based on the cellsowned value. Either pass the value held by the view controller into the cell, or set the image based on the view controllers value. Tracking the state of owned inside the cell will not work due to the nature of how cells are re-used.
 
OP
OP
R

Repa

New Member
#5
Ok. I am now storing the owned values in the CollectionViewController class and am returning the owned value in the itemAt function. This is working. The prepareForReuse does not change anythigng but I will still keep it there.
 
Top