У меня похожий случай, но мой формат данных - JSON, а не xml.Загрузка и асинхронная часть должны быть очень похожи.Я решил попробовать это с блоками Objective-C и методом dispatch_async в GCD.Важные части моего кода приведены ниже, с некоторыми ненужными деталями.
У меня есть NSDictionary, который я использую для кэширования изображений, называемых изображениями.Первый шаг - проверить, есть ли у меня изображение для текущего NSIndexPath.Если так, я просто возвращаю это изображение.Если нет, я создаю изображение заполнителя, запускаю загрузку реального изображения и возвращаю заполнитель.
Часть «начать загрузку реального изображения» состоит из проверки, существует ли очередь, которую я хочу использовать, уже существует, и если она не создается.Затем я выполняю асинхронный вызов в фоновом потоке для удобного метода NSData dataWithContentsOfURL.Это блокирующий вызов, но он работает в фоновом режиме, поэтому пользовательский интерфейс остается отзывчивым.Когда вызов возвращается, я создаю UIImage из данных, кэширую изображение и извлекаю ячейку для indexPath.Затем я делаю еще один вызов dispatch_async, который просто устанавливает свойство imageView.image для ячейки.Ключевым моментом здесь является использование dispatch_get_main_queue () для получения ссылки на очередь, которая управляет основным потоком, потому что только основной поток имеет разрешение на обновление пользовательского интерфейса.
RootViewController.h
#import <UIKit/UIKit.h>
@interface RootViewController : UITableViewController {
//An array of dictionary objects
NSArray *tweets;
//A place to cache images
NSDictionary *images;
// the dispatch queue to load images
dispatch_queue_t queue;
}
@property (nonatomic, retain) NSArray *tweets;
@property (nonatomic, retain) NSDictionary *images;
@end
RootViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = ...;
//set up the cell
....
cell.imageView.image = [self imageForRowAtIndexPath:indexPath];
return cell;
}
- (UIImage *)imageForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get the dictionary for the indexPath
NSDictionary *tweet = ...;
// get the user dictionary for the indexPath
NSDictionary *user = [tweet objectForKey:@"user"];
// get the user's id and check for a cached image first
NSString *userID = [user objectForKey:@"id_str"];
UIImage *image = [self.images objectForKey:userID];
if(!image)
{
// if we didn't find an image, create a placeholder image and
// put it in the "cache". Start the download of the actual image
image = [UIImage imageNamed:@"Placeholder.png"];
[self.images setValue:image forKey:userID];
//get the string version of the URL for the image
NSString *url = [user objectForKey:@"profile_image_url"];
// create the queue if it doesn't exist
if (!queue) {
queue = dispatch_queue_create("image_queue", NULL);
}
//dispatch_async to get the image data
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *anImage = [UIImage imageWithData:data];
[self.images setValue:anImage forKey:userID];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
//dispatch_async on the main queue to update the UI
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = anImage;
});
});
}
// return the image, it could be the placeholder, or an image from the cache
return image;
}