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\$ Commented Nov 14, 2016 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\$ Commented Nov 14, 2016 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\$ Commented Nov 14, 2016 at 5:35
  • \$\begingroup\$ @Jamal i started a bounty..i will see if there is a way i can cancel the bounty \$\endgroup\$ Commented Nov 14, 2016 at 5:55
  • 1
    \$\begingroup\$ Create a protocol that declares all shared functionality, then implement that protocol in your two types \$\endgroup\$ Commented Nov 15, 2016 at 2:45

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.