Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

share|improve this question

This question has an open bounty worth +50 reputation from Anish 웃 ending in 6 days.

This question has not received enough attention.

i want some improvement in my answer..if there is a different approach(MVVM/Protocols) to tackle this kind of problem, it is highly appreciate.

    
What exactly do you mean by your last question? Does this have to do with something not yet implemented (some particular case)? – Jamal 23 hours ago
    
@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. – Anish 웃 23 hours ago
    
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. – Jamal 23 hours ago
    
@Jamal i started a bounty..i will see if there is a way i can cancel the bounty – Anish 웃 23 hours ago
    
Only a mod can do that, which is why I first need to determine whether or not this question is off-topic. – Jamal 23 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.