我正在开发一个用户可以出售/购买的产品应用程序。该应用程序基于集合视图。集合视图具有集合单元格,其中显示产品图像缩略图。
以下代码从服务器获取产品图像,并等待下载所有图像,然后将它们显示在单元格中。以下代码有效,但用户需要等待 10-20 秒才能看到所有产品。有没有更好的处理方法?
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
[self loadFromURL];
dispatch_async(dispatch_get_main_queue(), ^{
});
});
}
-(void)loadFromURL {
NSURL *url = [NSURL URLWithString:@"http://myURL/productAll.php"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
pElements= (NSMutableArray *)responseObject;
[collectionView reloadData];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Product" message:[error localizedDescription]delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alertView show];
}];
[operation start];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return pElements.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ProductCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
cell.backgroundColor=[UIColor whiteColor];
NSString *arrayResult = [[pElements objectAtIndex:indexPath.row] objectForKey:@"image"];
NSData *data = [[NSData alloc] initWithBase64EncodedString:arrayResult options:NSDataBase64DecodingIgnoreUnknownCharacters];
cell.productImage.image = [[UIImage alloc] initWithData:data];
cell.productImage.layer.cornerRadius = 10;
cell.productImage.clipsToBounds = YES;
return cell;
}
您收到来自服务器的响应,其中所有图像的图像数据在响应中均采用 Base-64 编码。这意味着响应可能非常大,并且在下载所有内容之前不会向用户显示。
相反,您可以考虑重构服务器代码,使其不包含 base-64 格式的图像数据,而只包含稍后可用于检索图像的 URL(或某些标识符)。您的回复应该更小,并且能够更快地处理。
那么,当cellForItemAtIndexPath
被调用,而不是从原始响应中提取图像数据,而是延迟(异步)请求单元格的图像。 AFNetworking 提供了一个很好的UIImageView
类别在UIImageView+AFNetworking
从网络源异步检索图像。 (使用这个类别可以让您在进行异步图像检索时摆脱许多微妙问题的困扰。)
顺便说一句,如果您的图像大小不同,您可能希望在原始请求中包含图像的尺寸,以便可以预先适当调整单元格及其图像视图的大小,而不是在检索图像时调整它们的大小。
--
一些观察结果:
您无需派送[self loadFromURL]
到后台队列,因为它已经是异步的。我可能会用GET
请求的
你不能只是投射responseObject
to NSMutableArray
,因为它可能是不可变的。你真的应该使用NSArray
or use mutableCopy
if you really需要它是可变的。
您正在执行一些单元格配置cellForItemAtIndexPath
。其中大部分(剪辑、背景颜色等)都可以在 IB 中完成,所以我会在那里完成,而不是以编程方式完成。您可能需要以编程方式做的唯一一件事是圆角(而且,即使如此,我可能会用IBDesignable
子类,尽管这超出了这个问题的范围)。
因此,假设 (a) 你的数组有一个名为imageURL
这是图像的 URL; (b) 单元格具有固定大小的图像视图,您可以执行以下操作:
@interface ViewController ()
@property (nonatomic, strong) AFHTTPRequestOperationManager *manager;
@property (nonatomic, strong) NSArray *pElements;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.manager = [AFHTTPRequestOperationManager manager];
[self loadFromURL];
}
-(void)loadFromURL {
NSString *urlString = @"http://myURL/productAll.php";
[self.manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) {
self.pElements = responseObject;
[self.collectionView reloadData];
} failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Product" message:[error localizedDescription]delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alertView show];
}];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.pElements.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ProductCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
NSString *imageURL = self.pElements[indexPath.row][@"imageURL"];
[cell.productImage setImageWithURL:[NSURL URLWithString:imageURL]];
cell.productImage.layer.cornerRadius = 10;
return cell;
}
@end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)