3
\$\begingroup\$

I have implemented swipe functionality using UIPanGestureRecognizer in a project.

What I have done is added PanGesture to UIView:

self.panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panThisCell))
self.view.addGestureRecognizer(panGesture)

And its selector is as:

func panThisCell(recognizer:UIPanGestureRecognizer){

    if recognizer != panGesture{  return }

    let point = recognizer.locationInView(self.collectionView)
    let indexpath = self.collectionView.indexPathForItemAtPoint(point)
    if indexpath == nil{  return }
    guard let cell = self.collectionView.cellForItemAtIndexPath(indexpath!) as? TileCollectionViewCell else{

        return

    }
    .......
}

And helper methods that animates to show/hide background view are as follows which takes cell of class TileCollectionViewCell so that I don't have to typecast it later:

func resetConstraintToZero(cell:TileCollectionViewCell, animate:Bool,notifyDelegateDidClose:Bool){

        if (cell.startingRightLayoutConstraintConstant == 0 &&
            cell.contentViewRightConstraint.constant == 0) {
            //Already all the way closed, no bounce necessary
            return;
        }
        cell.contentViewRightConstraint.constant = -kBounceValue;
        cell.contentViewLeftConstraint.constant = kBounceValue;
        self.updateConstraintsIfNeeded(cell,animated: animate) {
            cell.contentViewRightConstraint.constant = 0;
            cell.contentViewLeftConstraint.constant = 0;

            self.updateConstraintsIfNeeded(cell,animated: animate, completionHandler: {

                cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant;
            })
        }
        cell.startPoint = CGPoint()
    }

    func setConstraintsToShowAllButtons(cell:TileCollectionViewCell, animate:Bool,notifyDelegateDidOpen:Bool){

        if (cell.startingRightLayoutConstraintConstant == self.getButtonTotalWidth(cell) &&
            cell.contentViewRightConstraint.constant == self.getButtonTotalWidth(cell)) {
            return;
        }
        cell.contentViewLeftConstraint.constant = -self.getButtonTotalWidth(cell) - kBounceValue;
        cell.contentViewRightConstraint.constant = self.getButtonTotalWidth(cell) + kBounceValue;

        self.updateConstraintsIfNeeded(cell,animated: animate) {
            cell.contentViewLeftConstraint.constant =  -(self.getButtonTotalWidth(cell))
            cell.contentViewRightConstraint.constant = self.getButtonTotalWidth(cell)

            self.updateConstraintsIfNeeded(cell,animated: animate, completionHandler: {(check) in

                cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant;
            })
        }
    }

I am thinking of implementing same swipe functionality on to another UICollectionView which is in the same ViewController, so I would like to reuse those methods. Custom cells are the exact same.

class TileCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var swipeView: UIView!
    @IBOutlet weak var customTextLbl: UILabel!
    @IBOutlet weak var customContentView: UIView!
    @IBOutlet weak var contentViewLeftConstraint: NSLayoutConstraint!
    @IBOutlet weak var contentViewRightConstraint: NSLayoutConstraint!


    var startPoint = CGPoint()
    var startingRightLayoutConstraintConstant = CGFloat()


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

}


class SecondTileCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var swipeView: UIView!
    @IBOutlet weak var customTextLbl: UILabel!
    @IBOutlet weak var customContentView: UIView!
    @IBOutlet weak var contentViewLeftConstraint: NSLayoutConstraint!
    @IBOutlet weak var contentViewRightConstraint: NSLayoutConstraint!


    var startPoint = CGPoint()
    var startingRightLayoutConstraintConstant = CGFloat()


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

}

I am thinking of making those helper methods accept AnyObject instead of TileCollectionViewCell and later downcast to the appropriate type and perform operations. However, this requires an if let which makes the code more messy.

func resetConstraintToZero(cell:AnyObject, animate:Bool,notifyDelegateDidClose:Bool){

        if let firstCell = cell as? TileCollectionViewCell {


            if (firstCell.startingRightLayoutConstraintConstant == 0 &&
                firstCell.contentViewRightConstraint.constant == 0) {
                //Already all the way closed, no bounce necessary
                return;
            }
            firstCell.contentViewRightConstraint.constant = -kBounceValue;
            firstCell.contentViewLeftConstraint.constant = kBounceValue;
            self.updateConstraintsIfNeeded(firstCell,animated: animate) {
                firstCell.contentViewRightConstraint.constant = 0;
                firstCell.contentViewLeftConstraint.constant = 0;

                self.updateConstraintsIfNeeded(firstCell,animated: animate, completionHandler: {

                    firstCell.startingRightLayoutConstraintConstant = firstCell.contentViewRightConstraint.constant;
                })
            }
            firstCell.startPoint = CGPoint()

        }else  {

            let secondCel = cell as! SecondTileCollectionViewCell

            if (secondCel.startingRightLayoutConstraintConstant == 0 &&
                secondCel.contentViewRightConstraint.constant == 0) {
                //Already all the way closed, no bounce necessary
                return;
            }
            secondCel.contentViewRightConstraint.constant = -kBounceValue;
            secondCel.contentViewLeftConstraint.constant = kBounceValue;
            self.updateConstraintsIfNeeded(secondCel,animated: animate) {
                secondCel.contentViewRightConstraint.constant = 0;
                secondCel.contentViewLeftConstraint.constant = 0;

                self.updateConstraintsIfNeeded(secondCel,animated: animate, completionHandler: {

                    secondCel.startingRightLayoutConstraintConstant = chartCel.contentViewRightConstraint.constant;
                })
            }
            secondCel.startPoint = CGPoint()
        }
    }

As you can see, the if else has the same job but only the class is varying. What kind of pattern should I use to deal with this case?

Here is the project

enter image description here

\$\endgroup\$
10
  • \$\begingroup\$ What exactly do you mean by your last question? Does this have to do with something not yet implemented (some particular case)? \$\endgroup\$ – Jamal Nov 14 '16 at 5:21
  • \$\begingroup\$ @Jamal Actually i can implement the same functionality repeating the code for another collection View..But i mean is there a way i can use the same code of helper methods for both collection view. \$\endgroup\$ – Anish Parajuli 웃 Nov 14 '16 at 5:25
  • \$\begingroup\$ I'll post this question in chat since I can't quite tell if it fits best here. Regardless, I'd recommend not starting a bounty so soon since cancellations are not guaranteed. \$\endgroup\$ – Jamal Nov 14 '16 at 5:35
  • \$\begingroup\$ @Jamal i started a bounty..i will see if there is a way i can cancel the bounty \$\endgroup\$ – Anish Parajuli 웃 Nov 14 '16 at 5:55
  • 1
    \$\begingroup\$ Create a protocol that declares all shared functionality, then implement that protocol in your two types \$\endgroup\$ – Alexander Nov 15 '16 at 2:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.