1

我有一个loadImages方法

- (void)loadImages {
   dispatch_async(dispatch_get_global_queue(0, 0), ^{
       //this method loads images from a url, processes them
       //and then adds them to a property of its view controller 
       //@property (nonatomic, strong) NSMutableArray *storedImages;
   });
}

单击按钮时,视图进入屏幕,并显示当前存在于 _storedImages 中的所有图像

- (void)displayImages {
   for (NSString *link in _storedImages) {
      //displayImages
   }
}

此设置的问题在于,如果用户在所有图像加载之前单击按钮,则并非所有图像都显示在屏幕上。

因此,如果单击按钮,我想显示一个 SVProgressHUD ,并且loadImages dispatch_async 方法仍在运行

那么,我如何跟踪这个 dispatch_async 的完成时间呢?因为如果我知道这一点,那么我可以在完成之前显示一个 SVProgressHUD。

附带说明一下,如果您知道如何动态加载/显示图像,该信息也会有所帮助,即您单击按钮,然后当您看到当前图像时,会下载并显示更多图像

来自第一次 iOS 开发者的感谢!


好的,我找到了一个解决方案,但效率非常低,我相信有更好的方法来做到这一点

1. Keep a boolean property doneLoadingImages which is set to NO
2. After the dispatch method finishes, set it to YES
3. In the display images method, have a while (self.doneLoadingImages == NO)
//display progress HUD until all the images a loaded
4

3 回答 3

6

请记住,这NSMutableArray不是线程安全的。您必须确保不要尝试同时从两个线程访问它。

使用布尔值来跟踪您是否仍在加载图像是可以的。loadImages看起来像这样:

- (void)loadImages {
    self.doneLoadingImages = NO;

    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        while (1) {
            UIImage *image = [self bg_getNextImage];
            if (!image)
                break;
            dispatch_async(dispatch_get_main_queue(), ^{
                [self addImage:image];
            });
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [self didFinishLoadingImages];
        });

    });
}

因此,我们将自己发送addImage:到每个图像的主队列中。该addImage:方法只会在主线程上调用,因此它可以安全地访问storedImages

- (void)addImage:(UIImage *)image {
    [self.storedImages addObject:image];
    if (storedImagesViewIsVisible) {
        [self updateStoredImagesViewWithImage:image];
    }
}

didFinishLoadingImages加载完所有图像后,我们发送自己。在这里,我们可以更新doneLoadingImages标志,并在必要时隐藏进度 HUD:

- (void)didFinishLoadingImages {
    self.doneLoadingImages = YES;
    if (storedImagesViewIsVisible) {
        [self hideProgressHUD];
    }
}

然后您的按钮操作可以检查doneLoadingImages属性:

- (IBAction)displayImagesButtonWasTapped:(id)sender {
    if (!storedImagesViewIsVisible) {
        [self showStoredImagesView];
        if (!self.doneLoadingImages) {
            [self showProgressHUD];
        }
    }
}
于 2013-04-03T21:34:45.960 回答
0

对于这类问题,我通常做的基本如下(粗略):

- (void)downloadImages:(NSArray*)arrayOfImages{

  if([arrayOfImages count] != 0)
  {
     NSString *urlForImage = [arrayOfImages objectAtIndex:0];
     // Start downloading the image

     // Image has been downloaded
     arrayOfImages = [arrayOfImages removeObjectAtIndex:0];
     // Ok let's get the next ones...
     [self downloadImages:arrayOfImages];
  }
  else
  {
   // Download is complete, use your images..
  }
}

您可以传递失败的下载次数,甚至可以传递将在之后接收图像的委托。

于 2013-04-03T21:25:40.873 回答
0

你放了一个“注释”,这可能会有所帮助,它允许你在图像下降时显示它们,我将 URL 存储在一个数组中(这里是字符串,但你可以做 NSURL 的数组)。

for(NSString *urlString in imageURLs)
{
    // Add a downloading image to the array of images
    [storedImages addObject:[UIImage imageNamed:@"downloading.png"]];

    // Make a note of the image location in the array    
    __block int imageLocation = [storedImages count] - 1; 

    // Setup the request    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
    [request setTimeoutInterval: 10.0];
    request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

    [NSURLConnection sendAsynchronousRequest:request
                  queue:[NSOperationQueue currentQueue]
                  completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                  // Check the result
                  NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
                  if (data != nil && error == nil && [httpResponse statusCode] == 200)
                  { 
                      storedImages[imageLocation] = [UIImage imageWithData:data];
                      [self reloadImages];
                  }
                  else
                  {
                      // There was an error
                      recommendedThumbs[imageLocation] = [UIImageimageNamed:@"noimage.png"];
                      [self reloadImages]
                  }
           }];
}

然后,您需要另一种方法来重新加载显示。如果图像在表格中,则 [[tableview] reloaddata];

-(void)reloadImages
于 2013-09-18T14:33:11.550 回答