当" didSelectItemAt"被称为

时间:2018-01-10 09:12:43

标签: ios swift xcode uicollectionview

我有一个UICollection视图。这些东西可以有3种状态:
- 积极的 - 中性
- 无效的 现在,这是UICollectionViewCell的代码:

class NGSelectStashCell: UICollectionViewCell {
    var status: String = "Active"
    @IBOutlet weak var statusImage: UIImageView!
    @IBOutlet weak var bgImage: UIImageView!
    @IBOutlet weak var titleLabel: UILabel!

    func changeStatus()
    {
        switch status {
        case "Active":
            status = "Neutral"
            //change bgImage
        case "Neutral":
            status = "Inactive"
            //change bgImage
        case "Inactive":
            status = "Active"
            //change bgImage
        default:
            print("No Status")
        }
    }

}

现在,当我声明UICollection视图时,我希望这样做,以便当用户点击"在UICell上,它将调出changeStatus()函数。如何在Delegate / DataSource代码中执行此操作?另外,如何保存"状态"每个单元格(如果我刷新UICollectionView,他们都不会返回"活动"?

/*
 ////////// UICOLLECTIONVIEW FUNCTIONS ///////////
*/
extension NewOnlineGameVC: UICollectionViewDelegate, UICollectionViewDataSource
{
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return availableStashes.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let stashCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ngStashCell", for: indexPath) as! NGSelectStashCell
        stashCell.titleLabel.text = availableStashes[indexPath.row]
        // stashCell.bgImage make image file with the same name as the name and change bg image to it.

        return stashCell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // code to toggle between active/neutral/inactive
        // do I re-declare stashCell as! NGSelectStashCell? or what do I do?

    }
}

2 个答案:

答案 0 :(得分:1)

获得所选单元格的引用后,您可以更改单元格的状态。

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard let cell = collectionView.cellForItem(at: indexPath) as? NGSelectStashCell else {return}
    cell.status = "Active"
    cell.changeStatus()
}

如果要保存单元格的状态,则必须进行模型驱动,即单元格中发生的任何事情都必须保存到模型中,并且当集合视图尝试重用以前的单元格时,必须在单元格中反映相同的模型实例化细胞。

你已经有了一个ModelStash模型,让我们以正确的方式使用它。

struct AvailableStash {
  var statusImage: UIImage?
  var backgroundImage: UIImage?
  var title: String?
  var status: String

  //Initilize properties properly
  init(with status: String) {
    self.status = status
  }
}

您的收藏视图必须是模型驱动的。例如:

class DemoCollectionView: UICollectionViewController {

  var availableStashes: [AvailableStash]?

  override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return availableStashes?.count ?? 0
  }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let stashCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ngStashCell", for: indexPath) as! NGSelectStashCell
    let item = availableStashes[indexPath.row]
    stashCell.titleLabel.text = item
    // stashCell.bgImage make image file with the same name as the name and change bg image to it.
    stashCell.statusImage = item.statusImage
    return stashCell
  }

  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard let cell = collectionView.cellForItem(at: indexPath) as? NGSelectStashCell else {return}
    cell.status = availableStashes[indexPath.row].status
    cell.changeStatus()
    availableStashes[indexPath.row].status = cell.status
  }
}

答案 1 :(得分:1)

不幸的是,解决方案比您想象的要复杂一些。集合视图可以排队并重用其单元以提高性能。这意味着滚动时单个单元格可能会用于多个对象。会发生什么事情,当你将改变第一个单元格上的状态并将滚动以便重复使用时,这个单元格将保留其状态,看起来好像另一个单元格已经改变了状态......

因此,您的真相来源必须始终是您的数据来源。无论availableStashes包含什么,它都需要包含其状态。例如,如果您目前有var availableStashes: [MyObject] = [],则可以像这样更改它:

typealias MySource = (status: String, object: MyObject)
var availableStashes: [MySource] = []

func setNewObjects(objects: [MyObject]) {
    availableStashes = objects.map { ("Neutral", $0) }
}

现在,您需要更新数据源中的对象,例如:

func changeStatusOfObjectAtIndex(_ index: Int, to newStatus: String) {
    availableStashes[index] = (newStatus, availableStashes[index].object)
}

所以在按下时你会这样做:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    changeStatusOfObjectAtIndex(indexPath.row, to: <#Your new status here#>)
    UICollectionView().reloadItems(at: [indexPath])
}

现在将触发此特定单元格的重新加载,您现在可以更新

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let stashCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ngStashCell", for: indexPath) as! NGSelectStashCell
    stashCell.dataObject = availableStashes[indexPath.row]
    return stashCell
}

在细胞内:

var dataObject: NewOnlineGameVC.MySource {
    didSet {
        titleLabel.text = dataObject.object
        switch dataObject.status {
        case "Active":
            //change bgImage
        case "Neutral":
            //change bgImage
        case "Inactive":
            //change bgImage
        default:
            print("No Status")
        }
    }
}

我希望这能解决你的问题。