从UICollectionViewCell

时间:2017-08-16 02:59:04

标签: ios swift uicollectionview

我有一个自定义的UICollectionViewCell,里面有一个按钮。当我点击按钮时,会在该子类中触发一个事件。我想在UICollectionView本身上触发一个事件,我可以在我的视图控制器中处理它。

的伪代码:

class MyCell : UICollectionViewCell {
    @IBAction func myButton_touchUpInside(_ sender: UIButton) {
        // Do stuff, then propagate an event to the UICollectionView
        Event.fire("cellUpdated")
    }
}

class MyViewController : UIViewController {
    @IBAction func collectionView_cellUpdated(_ sender: UICollectionView) {
        // Update stuff in the view controller 
        // to reflect changes made in the collection view
    }
}

理想情况下,我定义的事件将与Interface Builder中的默认操作出口一起显示,然后允许我将其拖到我的视图控制器代码中以创建上述collectionView_cellUpdated函数,类似于{{1}的方式用于公开自定义属性。

有没有办法在原生的Swift 3中实现这样的模式?或者,如果没有,任何使它成为可能的库?

2 个答案:

答案 0 :(得分:2)

最好的办法是为自定义单元格类制作自定义协议

protocol CustomCellProtocolDelegate {
   func custom(cell: YourCellClass, hadButton: UIButton, pressedWithInfo : [String:Any]?)
}

让这个单元类将此协议作为一个特殊的委托,并触发此委托:

class YourCellClass: UICollectionViewCell {

   var delegate : CustomCellProtocolDelegate?

   var indexPath : IndexPath? //Good practice here to have an indexPath parameter

   var yourButton = UIButton()

   init(frame: CGRect) {
      super.init(frame: frame)
      yourButton.addTarget(self, selector: #selector(triggerButton(sender:)))
   }
   func triggerButton(sender: UIButton) {
      if let d = self.delegate {
         d.custom(cell: self, hadButton: sender, pressedWithInfo : /*Add info if you want*/)
      }
   }

}

在您的控制器中,您将其与委托一致,然后将委托应用于cellForItem: atIndexPath中的每个单元格:

class YourControllerThatHasTheCollectionView : UIViewController, CustomCellProtocolDelegate {

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "identifier", for: indexPath) as! YourCellClass
        cell.delegate = self
        cell.indexPath = indexPath
        return cell
    }

   func custom(cell: YourCellClass, hadButton: UIButton, pressedWithInfo : [String:Any]?) {

        //Here you can process which button was selected, etc.. and apply your changes to your collectionview

   }

}

最佳做法是在pressedWithInfo内的委托方法中传递单元格的indexPath参数。它可以省去计算实际按下哪个单元格的麻烦;因此我通常会为每个UICollectionViewCell子类添加一个indexPath元素。更好的是,在协议方法中包含索引:

    protocol CustomCellProtocolDelegate {
       func custom(cell: YourCellClass, hadButton: UIButton, pressedAt: IndexPath, withInfo : [String:Any]?)
    }

    func triggerButton(sender: UIButton) {
       if let d = self.delegate {
           d.custom(cell: self, hadButton: sender, pressedAt: indexPath!, withInfo : /*Add info if you want*/)
       }
    }

答案 1 :(得分:2)

我完全不了解您的问题,但根据我的说法,您只需使用closureUIButton点按事件传递回UIViewController

示例:

<强> 1。自定义UICollectionViewCell

class MyCell: UICollectionViewCell
{
    var tapHandler: (()->())?

    @IBAction func myButton_touchUpInside(_ sender: UIButton)
    {
        tapHandler?()
    }
}

<强> 2。 MyViewController

class MyViewController: UIViewController, UICollectionViewDataSource
{
    //YOUR CODE..

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
        cell.tapHandler = {
            //Here you can do your custom handling
        }
        return cell
    }
}

如果您遇到任何问题,请告诉我。