2011-09-19 81 views
0

我创建了一个包含UIButtons的缩略图查看器,并且希望在每个按钮中都有一个微调框,直到图像从云中填充。我之前用单一的纺纱器做过这件事,但从来没有像这样做过。纺纱厂不会出现(也许是一个非主要的线程用户界面问题?)...我是否至少朝着正确的方向前进?提前致谢。正确使用具有多个UIActivityIndi​​catorViews的Grand Central Dispatch

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); 

感谢丹尼尔和布拉德的建议,下面,下面的舞蹈似乎工作:

- (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<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]; 
} 
+0

如果它可以帮助任何的代码似乎WO rk用于设备上的* some *缩略图,从不在模拟器上。 – diatrevolo

+1

在你修改后的代码中,我相信你可以用'dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_DEFAULT,0),^ {})'替换'-performSelectorInBackground:'来保存GCD中的所有内容,并避免为参数创建临时NSArray。 –

+0

噢,那应该是performSelectorInMainThread:withObject,无论如何。让我修改一下,然后尝试一些GCD选项。谢谢。 – diatrevolo

回答

1

是的,我相信你的问题是,你是从后台线程执行代码,UIKit的心不是线程安全,所以你应该只获得在背景中的图像数据,然后使用performSelectorOnMainTHread为了把图像和停止动画,像

-(void)setDataStopAnimating:(NSArray*)args 
{ 
    //get your arguments from the array and then run 
[thumb setImage:[UIImage imageWithData:imageData] forState:UIControlStateNormal]; 
       [newSpinner stopAnimating]; 
       [newSpinner removeFromSuperview]; 
       [newSpinner release]; 
} 

//then in your queue code 
     dispatch_async(queue2, ^(void){ 
       NSArray *args; //fill the array with the arguments 
       [self performSelectorOnMainThread:@selector(setDataAndStopAnimating:) withObject:args] 
      }); 
+1

哦,好的。我会给它一个旋风。我从来没有混合performSelector和GCD,谢谢。 – diatrevolo

+0

@diatrevolo我还没有尝试过,所以它可能无法正常工作,如果它没有,那么你可以只是执行selectorOnBackground获取数据,让我们知道它是否工作tho ... – Daniel

+0

UIImage * image = [UIImage imageWithData:imageData]我认为是线程安全的。 - [与UIImage类图像释放???崩溃](https://devforums.apple.com/message/360659#360659) –

相关问题