title: UICollectionView: activating, scrolling to, and assigning first responder to distant cell
body: <p>I've got a text field inside of a <code>UICollectionViewCell</code> that can receive first-responder status. The cell currently isn't visible on-screen, and I want to scroll to the cell based off of a button hit from a <code>UISegmentedControl</code>. There's two segments to this control… and a hit to the second segment should scroll to the first cell in the 2nd section of the <code>UICollectionView</code>. After this happens, the cell should get selected programatically, and then the text field inside of that cell is supposed to get first responder status and bring up the keyboard.</p>
  
  <p>What's happening now (inside my action method from a value change from the segmented control) is that a call to <code>-[UICollectionView selectItemAtIndexPath:animated:scrollPosition:]</code> isn't scrolling to it at all (and I'm using <code>UICollectionViewScrollPositionTop</code>; may as well be "<code>…None</code>"). If I thumb down the list manually, the cell is indeed selected (it gets a darker background color in that state), but the text field certainly doesn't have first responder status.</p>
  
  <p>To fix the scroll problem, I've been able to ascertain the position of the cell in the list, and scroll to the cell's content offset (I've also used <code>scrollRectToVisible</code> here). Then I manually select it (as well as telling the delegate to fire its appropriate method as well, where the cell's text field gains first responder status).</p>
  
  <pre><code>- (void)directionSegmentedControlChanged:(UISegmentedControl *)sender {
      NSIndexPath *path = [NSIndexPath indexPathForItem:0 inSection:sender.selectedSegmentIndex];
      UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:path];
      [self.collectionView setContentOffset:attributes.frame.origin animated:YES];
      [self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionNone];
      [self.collectionView.delegate collectionView:self.collectionView didSelectItemAtIndexPath:path];
  }
  
  - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
      BDKCollectionViewCell *cell = (BDKCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
      [cell.textField becomeFirstResponder];
  }
  </code></pre>
  
  <p>The problem here is that the cell as it's seen in <code>-[collectionView:didSelectItemAtIndexPath:]</code> is nil, because it's not in the visible cell set of the collection view when the method gets fired.</p>
  
  <p>What's the best way to solve this? I've tried tossing my scrolling code inside of a <code>[UIView animateWithDuration:animations:completion:]</code> block, and assigned first responder upon completion there, but manually animating the collection view in this manner neglects to load any of the cells that should be scrolled past. Any ideas?</p>
  
  <hr>
  
  <p><strong>Update</strong>: many thanks to @Esker, who suggested I simply perform the "focus selection" action after a delay using Grand Central Dispatch. My solution ended up looking like this.</p>
  
  <pre><code>- (void)directionSegmentedControlChanged:(UISegmentedControl *)sender {
      NSIndexPath *path = [NSIndexPath indexPathForItem:0  inSection:sender.selectedSegmentIndex];
  
      UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:path];
      [self.collectionView setContentOffset:attributes.frame.origin animated:YES];
  
      dispatch_time_t startAfter = dispatch_time(DISPATCH_TIME_NOW, 0.28 * NSEC_PER_SEC);
      dispatch_after(startAfter, dispatch_get_main_queue(), ^{
          [self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionNone];
          [self collectionView:self.collectionView didSelectItemAtIndexPath:path];
      });
  }
  </code></pre>