简体   繁体   English

调用“ didSelectItemAt”时从单元格内调用函数

[英]calling functions from within cell when “didSelectItemAt” is called

I have a UICollection view of things. 我有一个东西的UICollection视图。 these things can have 3 states: 这些东西可以有3种状态:
- Active -活跃
- Neutral -中立
- Inactive -无效
Now, here is the code for the UICollectionViewCell: 现在,这是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")
        }
    }

}

Now, when I declare the UICollection View, I want to make it so that when the user "clicks" on the UICell it will call out the changeStatus() function. 现在,当我声明UICollection View时,我想创建它,以便当用户在UICell上“单击”时,它将调用changeStatus()函数。 How can I do this in the Delegate/DataSource code?. 如何在Delegate / DataSource代码中执行此操作? Also, how do I save the "status" of the each cell (so that if I refresh the UICollectionView they don't all return to "active" ? 另外,如何保存每个单元格的“状态”(以便刷新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?

    }
}

You can change the status of the cell once you get the reference of the selected cell. 一旦获得所选单元格的引用,就可以更改单元格的状态。

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

If you want to save the status of the cell then it must be model driven ie anything happens to the cell must be saved to the model and the same model have to be reflecte in the cell when collection view tries to reuse the previously instantiated cells. 如果要保存单元格的状态,则必须由模型驱动,即,单元格发生的任何事情都必须保存到模型中,并且当集合视图尝试重用先前实例化的单元格时,必须在单元格中反映相同的模型。

You already have a model AvailableStash, lets use it in proper way. 您已经有一个模型AvailableStash,让我们以适当的方式使用它。

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

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

Your collection view must be model driven. 您的集合视图必须是模型驱动的。 For eg: 例如:

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
  }
}

Unfortunately the solution is a bit more complicated then you think. 不幸的是,解决方案要比您想象的要复杂一些。 Collection views may queue and reuse their cells for performance gains. 收集视图可以排队并重用其单元以获取性能。 That means that a single cell may and will be used for multiple objects when scrolling. 这意味着在滚动时单个单元格可以并且将用于多个对象。 What will happen is that when you will change the state on first cell and will scroll so it is reused then this cell will preserve its state and will look as if another cell has this changed state... 将会发生的事情是,当您将更改第一个单元格的状态并滚动以使其重新使用时,该单元格将保留其状态,并且看起来就像另一个单元格具有此更改的状态...

So your source of truth must always be your data source. 因此,您的真理来源必须始终是您的数据来源。 Whatever availableStashes contains it needs to also contain its state. 无论任何availableStashes包含它,还需要包含其状态。 So for instance if you currently have var availableStashes: [MyObject] = [] you can change it like this: 因此,例如,如果您当前有var availableStashes: [MyObject] = [] ,则可以这样更改:

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

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

Now on press you need to update the object in your data source for instance: 现在,在新闻发布时,您需要更新数据源中的对象,例如:

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

So on press you do: 因此,在新闻发布时,您需要执行以下操作:

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

This will now trigger a reload for this specific cell which you can now update like 现在,这将触发此特定单元格的重新加载,您现在可以像这样更新

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
}

And inside the cell: 在单元格内:

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")
        }
    }
}

I hope this clears your issue. 希望这能解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在didSelectItemAt中选择单元格时,取消选择cellForItemAt中的单元格 - Deselecting the cell in cellForItemAt when selecting cell in didSelectItemAt 与UITapGestureRecognizer一起使用时,不调用collectionView的didSelectItemAt - collectionView's didSelectItemAt not called when use it with UITapGestureRecognizer 在UICollectionViewCell中归档的可编辑文本阻止didSelectItemAt被调用 - Editable text filed in UICollectionViewCell blocks didSelectItemAt from being called didSelectItem没有被调用 - didSelectItemAt not being called CollectionView didSelectItemAt 没有被调用 - CollectionView didSelectItemAt is not getting called UICollectionView didSelectItemAt 未被调用 - UICollectionView didSelectItemAt not being called 默认情况下,didSelectItemAt项目将被调用,而尺寸收集视图单元格则被调用 - didSelectItemAt item by default size collection view cell is called instead Color Collection View Cell 以编程方式从collectionView Cell didSelectItemAt推送到新的ViewController-Swift - Pushing to new ViewController from collectionView Cell didSelectItemAt programmatically - swift collectionView didSelectItemAt indexPath 未调用 swift - collectionView didSelectItemAt indexPath not called swift 单元格的委托在 didSelectItemAt 中为零 - Cell's delegate is nil in didSelectItemAt
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM