在这个项目中,我使用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);
}];
答案 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];
}