Perform Segue from UICollectionViewCell Button different from Cell Click

前端 未结 3 1001
旧时难觅i
旧时难觅i 2021-02-06 15:27

I have a UICollectionViewCell, with a UIButton. And I have two different actions. The first one, when the user presses the cell, it will segue to anoth

3条回答
  •  庸人自扰
    2021-02-06 16:03

    You can not call performSegue from your UICollectionViewCell subclass, because there is no interface declared on UICollectionViewCell like that.

    The reason why it is working didSelectItemAtIndexPath() is because i suppose the delegate of your UICollectionView is a UIViewController subclass, what has the function called performSegueWithIdentifier:()`.

    You need to notify your UIViewController when the button was clicked in your UICollectionViewCell, for what you have various possibilities, like KVO or using delegate.

    Here is a little code sniplet, how to use KVO. This solution is great, as long as you do not care, in which cell was the button pressed.

    import UIKit
    
    class CollectionViewCell: UICollectionViewCell {
        @IBOutlet weak var button: UIButton!
    }
    
    class CollectionViewController: UIViewController {
        @IBOutlet weak var collectionView: UICollectionView!
    }
    
    extension CollectionViewController: UICollectionViewDataSource {
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 1
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) ->  UICollectionViewCell {
            let cell: CollectionViewCell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
            // Add your `UIViewController` subclass, `CollectionViewController`, as the target of the button
            // Check out the documentation of addTarget(:) https://developer.apple.com/reference/uikit/uicontrol/1618259-addtarget
            cell.button.addTarget(self, action: #selector(buttonTappedInCollectionViewCell), for: .touchUpInside)
            return cell
        }
    
        func buttonTappedInCollectionViewCell(sender: UIButton) {
            self.performSegue(withIdentifier: "toStoreFromMyDiscounts", sender: nil)
        }
    }
    

    EDIT: If you care, in which cell the touch event has happend, use the delegate pattern.

    import UIKit
    
    protocol CollectionViewCellDelegate: class {
        // Declare a delegate function holding a reference to `UICollectionViewCell` instance
        func collectionViewCell(_ cell: UICollectionViewCell, buttonTapped: UIButton)
    }
    
    class CollectionViewCell: UICollectionViewCell {
        @IBOutlet weak var button: UIButton!
        // Add a delegate property to your UICollectionViewCell subclass
        weak var delegate: CollectionViewCellDelegate?
    
        @IBAction func buttonTapped(sender: UIButton) {
            // Add the resposibility of detecting the button touch to the cell, and call the delegate when it is tapped adding `self` as the `UICollectionViewCell`
            self.delegate?.collectionViewCell(self, buttonTapped: button)
        }
    }
    
    class CollectionViewController: UIViewController {
        @IBOutlet weak var collectionView: UICollectionView!
    }
    
    extension CollectionViewController: UICollectionViewDataSource {
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 1
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) ->  UICollectionViewCell {
            let cell: CollectionViewCell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
            // Asssign the delegate to the viewController
            cell.delegate = self
            return cell
        }
    }
    
    // Make `CollectionViewController` confrom to the delegate 
    extension CollectionViewController: CollectionViewCellDelegate {
        func collectionViewCell(_ cell: UICollectionViewCell, buttonTapped: UIButton) {
            // You have the cell where the touch event happend, you can get the indexPath like the below 
            let indexPath = self.collectionView.indexPath(for: cell)
            // Call `performSegue`
            self.performSegue(withIdentifier: "toStoreFromMyDiscounts", sender: nil)
        }
    }
    

提交回复
热议问题