[英]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.