title: UIScrollView's content offset being reset
body: <p>I have been struggling for a long time with a problem with a UIScrollView.</p>
  
  <p>I have a <code>UIScrollVIew</code> that contains a <code>UITextView</code> as a  subview. When I select the text view a keyboard pops up. I want to resize the text view to fit exactly in the available space, and also scroll the scroll view so that the text view is positioned exactly in the visible space (not hidden by the keyboard).</p>
  
  <p>When the keyboard appears I call a method that calculates the appropriate size for the text view and then performs the following code:</p>
  
  <pre><code>[UIView animateWithDuration:0.3 
                   animations:^
   { 
       self.textView.frame = frame;
   }  
   ];
  
  [self.scrollView setContentOffset:CGPointMake(0,frame.origin.y) animated:YES];
  </code></pre>
  
  <p>(here frame is the appropriate frame for the text view).</p>
  
  <p>Unfortunately the scroll view does not always scroll to the correct position, especially when it is already at a non zero vertical content offset when I select the text view. I know that the content offset that I'm setting it to is correct.</p>
  
  <p>After a lot of testing I finally realized that what was happening was that after the animation completed, the scroll view was automatically scrolling again.</p>
  
  <p>This code does work:</p>
  
  <pre><code>UIView animateWithDuration:0.3 
                   animations:^
   { 
       self.textView.frame = frame;
   }
   completion:^(BOOL finished) {
       [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
   }
   ];
  </code></pre>
  
  <p>but it looks strange because the scroll view scrolls to the wrong position, then to the right one. </p>
  
  <p>Does anyone know how I can prevent the scroll view from changing it's content offset when the text view frame finishes its animation?</p>
  
  <p>I am testing using iOS 5.0.</p>
  
  <hr>
  
  <p>Here is a solution that I found that works. I'm still don't completely understand what's happening, possible it has something to do with the way my springs and struts are set. Basically I am shrinking the scroll view content size by the same amount that the text view shrinks.</p>
  
  <pre><code>- (void)keyboardDidShow:(NSNotification*)aNotification
  {
      NSDictionary* info = [aNotification userInfo];
  
      // Get the height of the keyboard
      CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
      kbRect = [self.view convertRect:kbRect fromView:nil];
      CGSize kbSize = kbRect.size;
  
      // Adjust the height of the text view to fit in the visible view
      CGRect frame = self.textView.frame;
      int visibleHeight = self.view.frame.size.height;
      visibleHeight -= kbSize.height;
      frame.size.height = visibleHeight;
  
      // Get the new scroll view content size
      CGSize contentSize = self.scrollView.contentSize;
      contentSize.height = contentSize.height - self.textView.frame.size.height + frame.size.height;
  
      [UIView animateWithDuration:0.1 
                       animations:^
       { 
           self.textView.frame = frame;
           // Note that the scroll view content size needs to be reset, or the scroll view
           // may automatically scroll to a new position after the animation is complete.
           self.scrollView.contentSize = contentSize;
           [self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
       }     
       ];
  
      // Turn off scrolling in scroll view
      self.scrollView.scrollEnabled = NO;
  }
  
  // Called when the UIKeyboardWillHideNotification is sent
  - (void)keyboardWillBeHidden:(NSNotification*)aNotification
  {
      // Update the view layout
      [UIView animateWithDuration:0.3 animations:^
       {
           self.scrollView.contentOffset = CGPointZero;
           [self updateViewLayout];
       }
       ];
  
      // Turn on scrolling in the scroll view
      self.scrollView.scrollEnabled = YES;
  }
  </code></pre>
  
  <p>(<code>[self updateViewLayout]</code> is a method that returns the text view to the correct height, and resets the scroll view content size, as well as making sure all the other subviews are properly positioned).</p>