如何从位于集合视图单元格内的步进器获取选定的 IndexPath?
How to get selected IndexPath from a stepper located inside a collection view cell?
我有一个集合视图,在集合视图单元格内有步进器,用于增加产品数量,如下图所示。
我需要知道,当我单击集合视图单元格上的步进器时。我如何知道该集合视图单元格的 indexPath.item
?所以我可以使用视图控制器中选定的 indexPath 修改数据?
所以如果我更改第二个单元格中的步进器,我将始终得到 indexPath.item = 1
我之前认为 indexPath
将来自下面的 didSelectItemAt
方法。但是 当我点击集合视图单元格内的步进器时,didSelectItemAt
方法似乎不会被触发。
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
所以我想我可以从 cellForRowAt IndexPath
获取 indexPath 并使用协议委托模式。这是我做的方法,我得到了错误的 indexPath
所以如果我改变第二个单元格中的步进器,我不会总是得到 indexPath.item = 1 ,它可以是 2,3,0 等
这里是视图控制器代码:
class WishListVC: UIViewController, ListProductCellDelegate {
var products = [Product]()
var selectedProduct : Product?
// method from ListProductCellDelegate
func stepperButtonDidTapped(at selectedIndexPath: IndexPath, stepperValue: Int) {
// get selectedIndexPath
// perform some action based on selectedIndexPath
}
}
extension WishListVC : UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return products.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WishListStoryboardData.CollectionViewIdentifiers.productSliderCell.rawValue, for: indexPath) as? ListProductCell else { return UICollectionViewCell()}
cell.productData = products[indexPath.item]
cell.indexPath = indexPath // I send the indexPath to the cell.
cell.delegate = self
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedProduct = products[indexPath.item]
performSegue(withIdentifier: WishListStoryboardData.SegueIdentifiers.toProductVC.rawValue, sender: nil)
}
}
这是集合视图单元格中的代码:
protocol ListProductCellDelegate {
func stepperButtonDidTapped( at selectedIndexPath: IndexPath, stepperValue: Int)
}
class ListProductCell: UICollectionViewCell {
var indexPath: IndexPath?
var delegate: ListProductCellDelegate?
var productData : Product? {
didSet {
updateUI()
}
}
@IBAction func stepperDidTapped(_ sender: GMStepper) {
guard let indexPath = indexPath, let collectionView = collectionView else {return}
self.delegate?.stepperButtonDidTapped(at: indexPath, stepperValue: Int(sender.value))
}
func updateUI() {
// update the UI in cell.
}
}
您有步进器,因为它是您操作方法中的 sender
。步进器有一个超级视图,它是单元格(您可能需要走不止一个超级视图才能到达单元格)。获得单元格后,您可以调用 indexPath(for:)
来获取索引路径。完毕。
https://developer.apple.com/documentation/uikit/uicollectionview/1618094-indexpath
您可以尝试将 tag
属性 添加到步进器。因此,当您单击步进器时,您可以监听其选择器并确定调用了哪个步进器。标签值应与项目索引相同。
像这样
cell.stepper.tag = indexPath.row
以上代码应该放在 cellForRowAt 委托函数中。
然后当用户点击步进器时调用函数并检查标签值
像这样
func stepperClicked(sender) {
//check sender.tag value
//Do something here with the tag value
}
在 Swift 中,回调闭包 可能是最有效的解决方案。它独立于索引路径、标签、视图层次结构 math 和协议。
在单元格中添加一个 callback
属性 来传递步进器实例。删除 indexPath
和 delegate
。协议根本不需要。
在IBAction
调用callback
并传递步进器实例
class ListProductCell: UICollectionViewCell {
var callback: ((GMStepper) -> Void)?
var productData : Product? {
didSet {
updateUI()
}
}
@IBAction func stepperDidTapped(_ sender: GMStepper) {
callback?(sender)
}
func updateUI() {
// update the UI in cell.
}
}
在 cellForItemAt
的控制器中设置闭包并处理回调。方法中捕获索引路径。
并且不要 guard
细胞。强制解开它。代码不能崩溃。如果是这样,则表明存在 design 错误。使用 guard
方式,table 视图将不显示任何内容,您不知道为什么。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WishListStoryboardData.CollectionViewIdentifiers.productSliderCell.rawValue, for: indexPath) as! ListProductCell
cell.productData = products[indexPath.item]
cell.callback = { stepper in
// handle the callback
}
return cell
}
我有一个集合视图,在集合视图单元格内有步进器,用于增加产品数量,如下图所示。
我需要知道,当我单击集合视图单元格上的步进器时。我如何知道该集合视图单元格的 indexPath.item
?所以我可以使用视图控制器中选定的 indexPath 修改数据?
所以如果我更改第二个单元格中的步进器,我将始终得到 indexPath.item = 1
我之前认为 indexPath
将来自下面的 didSelectItemAt
方法。但是 当我点击集合视图单元格内的步进器时,didSelectItemAt
方法似乎不会被触发。
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
所以我想我可以从 cellForRowAt IndexPath
获取 indexPath 并使用协议委托模式。这是我做的方法,我得到了错误的 indexPath
所以如果我改变第二个单元格中的步进器,我不会总是得到 indexPath.item = 1 ,它可以是 2,3,0 等
这里是视图控制器代码:
class WishListVC: UIViewController, ListProductCellDelegate {
var products = [Product]()
var selectedProduct : Product?
// method from ListProductCellDelegate
func stepperButtonDidTapped(at selectedIndexPath: IndexPath, stepperValue: Int) {
// get selectedIndexPath
// perform some action based on selectedIndexPath
}
}
extension WishListVC : UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return products.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WishListStoryboardData.CollectionViewIdentifiers.productSliderCell.rawValue, for: indexPath) as? ListProductCell else { return UICollectionViewCell()}
cell.productData = products[indexPath.item]
cell.indexPath = indexPath // I send the indexPath to the cell.
cell.delegate = self
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedProduct = products[indexPath.item]
performSegue(withIdentifier: WishListStoryboardData.SegueIdentifiers.toProductVC.rawValue, sender: nil)
}
}
这是集合视图单元格中的代码:
protocol ListProductCellDelegate {
func stepperButtonDidTapped( at selectedIndexPath: IndexPath, stepperValue: Int)
}
class ListProductCell: UICollectionViewCell {
var indexPath: IndexPath?
var delegate: ListProductCellDelegate?
var productData : Product? {
didSet {
updateUI()
}
}
@IBAction func stepperDidTapped(_ sender: GMStepper) {
guard let indexPath = indexPath, let collectionView = collectionView else {return}
self.delegate?.stepperButtonDidTapped(at: indexPath, stepperValue: Int(sender.value))
}
func updateUI() {
// update the UI in cell.
}
}
您有步进器,因为它是您操作方法中的 sender
。步进器有一个超级视图,它是单元格(您可能需要走不止一个超级视图才能到达单元格)。获得单元格后,您可以调用 indexPath(for:)
来获取索引路径。完毕。
https://developer.apple.com/documentation/uikit/uicollectionview/1618094-indexpath
您可以尝试将 tag
属性 添加到步进器。因此,当您单击步进器时,您可以监听其选择器并确定调用了哪个步进器。标签值应与项目索引相同。
像这样
cell.stepper.tag = indexPath.row
以上代码应该放在 cellForRowAt 委托函数中。
然后当用户点击步进器时调用函数并检查标签值
像这样
func stepperClicked(sender) {
//check sender.tag value
//Do something here with the tag value
}
在 Swift 中,回调闭包 可能是最有效的解决方案。它独立于索引路径、标签、视图层次结构 math 和协议。
在单元格中添加一个 callback
属性 来传递步进器实例。删除 indexPath
和 delegate
。协议根本不需要。
在IBAction
调用callback
并传递步进器实例
class ListProductCell: UICollectionViewCell {
var callback: ((GMStepper) -> Void)?
var productData : Product? {
didSet {
updateUI()
}
}
@IBAction func stepperDidTapped(_ sender: GMStepper) {
callback?(sender)
}
func updateUI() {
// update the UI in cell.
}
}
在 cellForItemAt
的控制器中设置闭包并处理回调。方法中捕获索引路径。
并且不要 guard
细胞。强制解开它。代码不能崩溃。如果是这样,则表明存在 design 错误。使用 guard
方式,table 视图将不显示任何内容,您不知道为什么。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WishListStoryboardData.CollectionViewIdentifiers.productSliderCell.rawValue, for: indexPath) as! ListProductCell
cell.productData = products[indexPath.item]
cell.callback = { stepper in
// handle the callback
}
return cell
}