如果您知道它被调用了n次,请等待异步任务完成

时间:2015-12-11 11:49:36

标签: ios objective-c iphone objective-c-blocks

在这个项目中,我使用Foursquare API来获取每个场地的一些场地和一张照片。当我有这些数据时,我正在重新加载TableView以显示所有信息。

首先我收集场地,其次是每个场地,我都是从foursquare API拍照。

我在这个项目中使用RestKit库,我正在调用这个方法n次(每个场地一次)。当它完成时,我想将我拍摄的所有照片显示在桌面视图中。

- (void)requestVenuePhoto:(Venue *)thisVenue{
  //...
  //...
  [[RKObjectManager sharedManager] getObjectsAtPath:objectPath parameters:queryParams success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
  {
    [self.photos addObjectsFromArray:mappingResult.array];
    //[self.tableView reloadData];

  } failure:^(RKObjectRequestOperation *operation, NSError *error) {
    NSLog(@"What do you mean by 'there is no photos?': %@", error);
    dispatch_group_leave(resolveVenuePhotos);
  }]; 
}

问题在于我无法使用dispatch_group_leave,因为它不会被调用一次。 有没有办法很好地做到这一点?

更新,现在我正在使用计数器来解决问题:

[[RKObjectManager sharedManager] getObjectsAtPath:objectPath parameters:queryParams success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
    [self.photos addObjectsFromArray:mappingResult.array];
    venuesPhotoCounter++;
    if (venuesPhotoCounter == _venues.count)
    {
        [self.tableView reloadData];
    }

} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    NSLog(@"What do you mean by 'there is no photos?': %@", error);
}];

2 个答案:

答案 0 :(得分:1)

这不是您问题的直接答案,但我认为它可以解决您的问题。

您不应加载所有图片,只能重新加载表格。你应该:

  • 加载项目列表,并在完成处理程序中重新加载表(如果在后台线程上运行完成处理程序,请确保在主线程上重新加载)。

  • 然后,在tableview数据源的tableView:cellForItemAtIndexPath:方法中,开始加载所请求项目的图像。还要记下当前的indexPath(通常只是行),例如在单元格的tag或自定义单元格属性中。在该请求的完成处理程序中,解码图像(在后台),然后在检查该单元格仍为同一indexPath(即该单元格尚未被重用)后,将其分配给您的单元格(在主线程上) )。

使用标准NSURLSession的示例(基于单个部分,数据位于_items实例变量中):

- tableView:(UITableView *)tableView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MyItem *item = _items[indexPath.row];
    MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:@"whatever"];
    // configure the rest of the cell: labels, etc.
    cell.tag = indexPath.row;
    [[[NSURLSession sharedSession] dataTaskWithURL:item.url
                                 completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
    {
        // Remember this runs on a background thread
        if (cell.tag == indexPath.row && !error && data)
        {
            UIImage *image = [UIImage imageWithData:data];
            dispatch_async(dispatch_get_main_queue(),^
            {
                cell.myImageView.image  = image;
            });
        }
    }] resume];
}

答案 1 :(得分:1)

Apple上传了一个名为“LazyTableImages”的项目here 。所以我把它包起来并制作了一些可能适合你的用例的范例。

 - (void)startDownload
    {
        NSURLRequest *request = [NSURLRequest requestWithURL:self.venue.imageURL];


        // create an session data task to obtain and download the app icon
        _sessionTask = [[NSURLSession sharedSession] dataTaskWithRequest:request
                                                       completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

            // in case we want to know the response status code
            NSInteger HTTPStatusCode = [(NSHTTPURLResponse *)response statusCode];


            if (error != nil)
            {
                if ([error code] == NSURLErrorAppTransportSecurityRequiresSecureConnection)
                {
                    // if you get error NSURLErrorAppTransportSecurityRequiresSecureConnection (-1022),
                    // then your Info.plist has not been properly configured to match the target server.
                    //
                    abort();
                }
            }

            [[NSOperationQueue mainQueue] addOperationWithBlock: ^{

                // Set appIcon and clear temporary data/image
                UIImage *image = [[UIImage alloc] initWithData:data];
                if (HTTPStatusCode == 200) {
                    if (image.size.width != kAppIconSize || image.size.height != kAppIconSize)
                    {
                        CGSize itemSize = CGSizeMake(kAppIconSize, kAppIconSize);
                        UIGraphicsBeginImageContextWithOptions(itemSize, NO, 0.0f);
                        CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
                        [image drawInRect:imageRect];
                        self.venue.image = UIGraphicsGetImageFromCurrentImageContext();
                        UIGraphicsEndImageContext();
                    }
                    else
                    {
                        self.venue.image = image;
                    }
                }
                else {// If anything goes wrong we should use a placeholder image
                    self.venue.image = [UIImage imageNamed:@"Placeholder.png"];
                }



                // call our completion handler to tell our client that our icon is ready for display
                if (self.completionHandler != nil)
                {
                    self.completionHandler();
                }
            }];
        }];

        [self.sessionTask resume];
    }