title: Correct usage of Grand Central Dispatch with multiple UIActivityIndicatorViews
body: <p>I am creating a thumbnail viewer consisting of UIButtons, and want to have a spinner in each button until the image gets populated from the cloud.  I've done this with single spinners before, but never en masse like this.  The spinners aren't coming up (maybe a non-main thread UI issue?)...am I at least headed in the right direction?  Thanks in advance.</p>
  
  <pre><code>dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
  dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
  dispatch_apply(numberOfThumbs, queue, ^(size_t i){
      Post *post = [arrayOfPosts objectAtIndex:i];
      UIActivityIndicatorView *newSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
      UIButton *currentThumb = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
      [currentThumb setFrame:CGRectMake((105.5 * (i%3))+3.5, ((i/3)*105.5) + 3.5, 102, 102)];
      [newSpinner setFrame:CGRectMake(54 - spinner.frame.size.width/2, 54 - spinner.frame.size.height/2, spinner.frame.size.width, spinner.frame.size.height)];
      [currentThumb addSubview:newSpinner];
      [newSpinner startAnimating];
      [thumbnails addObject:currentThumb];
      dispatch_async(queue2, ^(void){
          [currentThumb setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:post.thumbUrl]]] forState:UIControlStateNormal];
          [newSpinner stopAnimating];
          [newSpinner removeFromSuperview];
          [newSpinner release];
      });
      [currentThumb release];
  });
  dispatch_release(queue);
  dispatch_release(queue2);
  </code></pre>
  
  <p>Thanks to Daniel and Brad's suggestion, below, the following dance seems to work:</p>
  
  <pre><code>    - (id)initWithArrayOfPosts:(NSArray*)posts
      {
          self = [super initWithNibName:nil bundle:nil];
          if (self) {
              // Custom initialization
              arrayOfPosts = [posts retain];
              numberOfThumbs = [arrayOfPosts count];
              oldDequeueFactor = 0;
              oldYOffset = 0.0;
              thumbnails = [[NSMutableArray alloc] initWithCapacity:15];
              mainScrollView = [[UIScrollView alloc] init];
              [mainScrollView setFrame:self.view.frame];
              [mainScrollView setContentSize:CGSizeMake(self.view.frame.size.width, 109 * (ceilf((float)numberOfThumbs/3.0)))];
              [mainScrollView setDelegate:self];
              [mainScrollView setBackgroundColor:[UIColor whiteColor]];
              [self setView:mainScrollView];
  
              for (int i=0; i&lt;numberOfThumbs; i++) {
                  UIActivityIndicatorView *newSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
                  UIButton *currentThumb = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
                  [currentThumb setFrame:CGRectMake((105.5 * (i%3))+3.5, ((i/3)*105.5) + 3.5, 102, 102)];
                  [newSpinner setFrame:CGRectMake(54 - newSpinner.frame.size.width/2, 54 - newSpinner.frame.size.height/2, newSpinner.frame.size.width, newSpinner.frame.size.height)];
                  [currentThumb addSubview:newSpinner];
                  [newSpinner startAnimating];
                  [thumbnails addObject:currentThumb];
                  [currentThumb release];
                  [mainScrollView addSubview:[thumbnails objectAtIndex:i]];
                  [self getImageDataAsynchronouslyForThumbnail:[thumbnails objectAtIndex:i] forIndex:i andRemoveSpinner:newSpinner];
              }
          }
          return self;
      }
  
      - (void)getImageDataAsynchronouslyForThumbnail:(UIButton*)thumb forIndex:(int)index andRemoveSpinner:(UIActivityIndicatorView *)spinner
  {
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
  
      dispatch_async(queue, ^(void){
          Post *post = [arrayOfPosts objectAtIndex:index];
          UIImage *thisImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:post.thumbUrl]]];
          NSArray *args = [NSArray arrayWithObjects:thisImage, thumb, spinner, nil];
          if ([args count] == 3) { //use this array to verify I have all info I need
              dispatch_sync(dispatch_get_main_queue(), ^(void) {
                  [self setImage:[args objectAtIndex:0] ForThumbnail:[args objectAtIndex:1] andStopAnimatingSpinner:[args objectAtIndex:2]];
              });
          } else {
              [self getImageDataAsynchronouslyForThumbnail:thumb forIndex:index andRemoveSpinner:spinner];
              return;
          }
      });
  
      dispatch_release(queue);
  
  }
  
  - (void)setImage:(UIImage*)image ForThumbnail:(UIButton *)thumb andStopAnimatingSpinner:(UIActivityIndicatorView *)spinner
  {
      [thumb setImage:image forState:UIControlStateNormal];
      [spinner stopAnimating];
      [spinner removeFromSuperview];
      [spinner release];
  }
  </code></pre>