title: When moving a UILabel vertically with a UIPanGestureRecognizer, how do I stop them from going too far in either direction?
body: <p>I'm trying to make the user be able to move the <code>UILabel</code> up and down across the view by attaching a <code>UIPanGestureRecognizer</code> to the <code>UILabel</code> and subsequently altering the constant of a constraint from the <code>UILabel</code> to the top of its view. So basically if the gesture recognizer detects them moving down 12pts, move the constant of the constraint 12pts to move the <code>UILabel</code>.</p>
  
  <p>However, I want them to be stopped from moving further when they hit a certain vertical point (both too high or too low). I could just check the translation of the pan gesture, but my <code>UILabel</code> can be any number of lines, so if it's five lines instead of one, obviously it can't be panned down quite as far, so I can't rely on the translation of the pan gesture, I have to take into account the size of the label.</p>
  
  <p>So I started monitoring its frame, and it works well, but in my implementation there's an annoying result where if they pan completely to the bottom limit, they have to pan really far back up before the <code>UILabel</code> "catches up" and comes with it (though no such problem exists when they hit the top boundary). Basically, they pan down to the bottom limit, and when they pan back up (this is all in the same gesture) it "sticks" momentarily until they pan far enough up, then it jumps up with their finger.</p>
  
  <p>Here's the code I'm using to accomplish this:</p>
  
  <pre><code>- (void)textLabelPanned:(UIPanGestureRecognizer *)panGestureRecognizer {
      if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) {
          _textDistanceFromTopBeforeMove = self.textToReadLabelPositionFromTopConstraint.constant;
      }
      else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) {
          NSNumber *textDistanceFromTop = @(self.textToReadLabelPositionFromTopConstraint.constant);
          [[NSUserDefaults standardUserDefaults] setObject:textDistanceFromTop forKey:@"TextDistanceFromTop"];
      }
      else {
          if (CGRectGetMinY(self.textToReadLabel.frame) &gt;= [UIScreen mainScreen].bounds.origin.y + CLOSEST_TEXT_DISTANCE_TO_TOP &amp;&amp; CGRectGetMaxY(self.textToReadLabel.frame) &lt;= [UIScreen mainScreen].bounds.size.height - CLOSEST_TEXT_DISTANCE_TO_BOTTOM) {
                  self.textToReadLabelPositionFromTopConstraint.constant = _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y;
          }
          else if ([panGestureRecognizer translationInView:self.mainView].y &gt; 0) {
              if (CGRectGetMaxY(self.textToReadLabel.frame) + _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y &lt; [UIScreen mainScreen].bounds.size.height - CLOSEST_TEXT_DISTANCE_TO_BOTTOM) {
                  self.textToReadLabelPositionFromTopConstraint.constant = _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y;
              }
          }
          else if ([panGestureRecognizer translationInView:self.mainView].y &lt; 0) {
              if (CGRectGetMinY(self.textToReadLabel.frame) + _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y &gt; [UIScreen mainScreen].bounds.origin.y + CLOSEST_TEXT_DISTANCE_TO_TOP) {
                  self.textToReadLabelPositionFromTopConstraint.constant = _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y;
              }
          }
  
  
          // If one of the options views are present and the user pans really low, hide the options as to allow the user to see where they're panning
          if (_inSpeedChangingMode) {
              if (CGRectGetMaxY(self.textToReadLabel.frame) &gt; CGRectGetMinY(self.progressBar.frame) - 10) {
                  [self showWordOptions:nil];
              }
          }
          else if (_inTextChangingMode) {
              if (CGRectGetMaxY(self.textToReadLabel.frame) &gt; CGRectGetMinY(self.progressBar.frame) - 10) {
                  [self showTextOptions:nil];
              }
          }
      }
  }
  </code></pre>
  
  <p>What exactly am I doing wrong that would be causing it to "stick"? And is there perhaps a better way to be doing this?</p>