如何在UICollectionView中删除单元格后更新属于UICollectionViewCell的按钮标记?

时间:2016-03-04 13:02:06

标签: ios swift uicollectionview uicollectionviewcell

这是一个我已经坚持了很长一段时间的问题。 这是代码

let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0)
collectionViewLove?.performBatchUpdates({() -> Void in

self.collectionViewLove?.deleteItemsAtIndexPaths([indexPath])
self.wishlist?.results.removeAtIndex(indexPath.row)

self.collectionViewLove?.reloadData()}, completion: nil)}

我在每个UICollectionViewCell内都有一个按钮,可以在点击时将其删除。我检索indexPath的唯一方法是通过按钮标记。我在

中初始化了按钮标签
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell    

但是每次删除时,第一次删除相应的单元格,而下次删除单击后单击的单元格。原因是当我调用函数reloadData()时,我的按钮标记没有得到更新。 理想情况下,当我拨打reloadData()时,

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
应该调用

并更新每个单元格的按钮标记。但那并没有发生。解决任何人?

编辑:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    collectionView.registerNib(UINib(nibName: "LoveListCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "Cell")
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! LoveListCollectionViewCell
    cell.imgView.hnk_setImageFromURL(NSURL(string: (wishlist?.results[indexPath.row].image)!)!, placeholder: UIImage(named: "preloader"))
    let item = self.wishlist?.results[indexPath.row]
    cell.layer.borderColor = UIColor.grayColor().CGColor
    cell.layer.borderWidth = 1
    cell.itemName.text = item?.title
    cell.itemName.numberOfLines = 1
    if(item?.price != nil){
        cell.price.text = "\u{20B9} " + (item?.price.stringByReplacingOccurrencesOfString("Rs.", withString: ""))!
    }
    cell.price.adjustsFontSizeToFitWidth = true
    cell.deleteButton.tag = indexPath.row
    cell.deleteButton.addTarget(self, action: "removeFromLoveList:", forControlEvents: .TouchUpInside)
    cell.buyButton.tag = indexPath.row
    cell.buyButton.backgroundColor = UIColor.blackColor()
    cell.buyButton.addTarget(self, action: "buyAction:", forControlEvents: .TouchUpInside)
    return cell
}

3 个答案:

答案 0 :(得分:3)

有几件事:

  1. 您在cellForItemAtIndexPath做了太多工作 - 您真的希望尽可能快地完成工作。例如,您只需要为collectionView注册一次nib - viewDidLoad()是一个很好的地方。此外,您应该在单元格的prepareForReuse()方法中设置单元格的初始状态,然后仅使用cellForItemAtIndexPath更新项目中的自定义状态。

  2. 在删除完成之前,您不应重新加载数据。将reloadData移动到完成块中,以便删除方法完成,并且视图有时间更新其索引。

  3. 但是,如果您不必首先拨打reloadData,那会更好。您的实现将按钮的标记绑定到indexPath,但这些标记在不同的时间发生变异。把按钮的标签绑在比如愿望清单项ID上怎么样?然后,您可以根据ID查找相应的indexPath。

  4. 修改后的代码看起来像这样(未经测试但未经过语法检查):

    // In LoveListCollectionViewCell
    override func prepareForReuse() {
        // You could also set these in the cell's initializer if they're not going to change
        cell.layer.borderColor = UIColor.grayColor().CGColor
        cell.layer.borderWidth = 1
        cell.itemName.numberOfLines = 1
        cell.price.adjustsFontSizeToFitWidth = true
        cell.buyButton.backgroundColor = UIColor.blackColor()
    }
    
    // In your UICollectionView class
    
    // Cache placeholder image since it doesn't change
    private let placeholderImage = UIImage(named: "preloader")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.registerNib(UINib(nibName: "LoveListCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "Cell")
    }
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! LoveListCollectionViewCell
        cell.imgView.hnk_setImageFromURL(NSURL(string: (wishlist?.results[indexPath.row].image)!)!, placeholder: placeholderImage)
    
        let item = self.wishlist?.results[indexPath.row]
        cell.itemName.text = item?.title
        if(item?.price != nil){
            cell.price.text = "\u{20B9} " + (item?.price.stringByReplacingOccurrencesOfString("Rs.", withString: ""))!
        }
        cell.deleteButton.tag = item?.id
        cell.deleteButton.addTarget(self, action: "removeFromLoveList:", forControlEvents: .TouchUpInside)
        cell.buyButton.tag = item?.id
        cell.buyButton.addTarget(self, action: "buyAction:", forControlEvents: .TouchUpInside)
        return cell
    }
    
    func removeFromLoveList(sender: AnyObject?) {
        let id = sender.tag
        let index = wishlist?.results.indexOf { $0.id == id }
        let indexPath = NSIndexPath(forRow: index, inSection: 0)
    
        collectionViewLove?.deleteItemsAtIndexPaths([indexPath])
        wishlist?.results.removeAtIndex(index)
    }
    

答案 1 :(得分:2)

除非需要显示单元格,否则将数据存储在单元格中可能不是一个好主意。相反,您可以依靠UICollectionView为您提供正确的indexPath,然后将其用于从数据源中删除并更新集合视图。 为此,请使用带有单元格的委托模式。

1.定义控制器/数据源应符合的协议。

protocol DeleteButtonProtocol {
    func deleteButtonTappedFromCell(cell: UICollectionViewCell) -> Void
}

2.将一个委托属性添加到您的自定义单元格,该单元格将在删除操作上回调控制器。重要的是将单元格作为self传递给该调用。

class CustomCell: UICollectionViewCell {
     var deleteButtonDelegate: DeleteButtonProtocol!
    // Other cell configuration

    func buttonTapped(sender: UIButton){
        self.deleteButtonDelegate.deleteButtonTappedFromCell(self)
    }
}

3.然后在控制器中执行协议功能来处理删除操作。在这里,您可以从collectionView获取项目的indexPath,它可以用于删除数据并从collectionView中删除单元格。

class CollectionViewController: UICollectionViewController, DeleteButtonProtocol {
    // Other CollectionView Stuff

    func deleteButtonTappedFromCell(cell: UICollectionViewCell) {
        let deleteIndexPath = self.collectionView!.indexPathForCell(cell)!
        self.wishList.removeAtIndex(deleteIndexPath.row)

    self.collectionView?.performBatchUpdates({ () -> Void in
        self.collectionView?.deleteItemsAtIndexPaths([deleteIndexPath])
     }, completion: nil)
   }
    }

4.确保在配置时为单元设置委托,以便委托回调某个地方。

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        //Other cell configuring here
        var cell = collectionView.dequeueReusableCellWithReuseIdentifier("identifier", forIndexPath: indexPath)
        (cell as! CustomCell).deleteButtonDelegate = self
        return cell
    }
}

答案 2 :(得分:1)

我遇到了类似的问题,我通过在完成块中重新加载集合视图找到答案。

只需更新您的代码即可。

let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0)

collectionViewLove?.performBatchUpdates({
    self.collectionViewLove?.deleteItemsAtIndexPaths([indexPath])
    self.wishlist?.results.removeAtIndex(indexPath.row)
}, completion: {
    self.collectionViewLove?.reloadData()
})

UICollectionView Performing Updates using performBatchUpdates中由Nik提及