加载

时间:2017-01-31 23:55:51

标签: ios objective-c uicollectionview

我有一个collectionView(productCollectionView),它根据类别(电子,汽车,商品等)从服务中获取数据。

让我们想象用户决定在电子类别中提取数据,同时加载数据,用户更改了类别并获取新数据集。

我已经实现了以下逻辑,但它有点慢。有更好的方法吗?

-(void) refreshProducts
{
    if([self.pElements count]){
        [self.pElements removeAllObjects];
        [self.productCollectionView reloadData];
    }
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^(void) {
        [self loadFromURL]; // fetch new data
        dispatch_async(dispatch_get_main_queue(), ^{
        });
    });
}

-(void)loadFromURL {   

    NSMutableDictionary * params = [[NSMutableDictionary alloc]init];
    NSString * category = [[NSUserDefaults standardUserDefaults]objectForKey:@"category"];
    if (category != NULL && ![category isEqualToString: @""]) {
        params[@"category"] = category;
    }

   // offset increments based on scrolling down, +20
    params[@"offset"] = [NSString stringWithFormat:@"%d",offset];

    [self.manager POST:PRODUCT_URL parameters:params success:^(AFHTTPRequestOperation * _Nonnull operation, id responseObject) {
            // getting only 20 data every time, and append to the existing array
            [self.pElements addObjectsFromArray:responseObject];
            [self.productCollectionView reloadData];
    } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) {
    }];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
   __weak ProductCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];        
    cell.productImage.image = [cell.productImage.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    NSString *URL =[NSString stringWithFormat:@"http://www.xxxx.com/xxxx/images/%@", [[[[pElements objectAtIndex:indexPath.row]objectForKey:@"pdetail"] objectForKey:@"images"]objectForKey:@"pimagePath"]];
    cell.productImage.layer.cornerRadius = 10;        
    NSURL *url = [NSURL URLWithString:URL];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [cell.productImage setImageWithURLRequest:request
                          placeholderImage:nil
                                   success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {

                                       cell.productImage.image = image;
                                       [cell setNeedsLayout];

                                   } failure:nil];

    return cell;
 }

2 个答案:

答案 0 :(得分:0)

您发布的代码太过模糊,我们无法提供太多帮助。

看起来您的loadFromURL方法加载了所有产品,然后告诉收集视图在完成后重新加载。

如果为true,那将产生延迟,因为在完成所有内容加载之前不会发生任何事情。最好在collectionView(_:cellForItemAt:)中一次请求一个项目,将其内容保存到磁盘上的文件中,然后将该内容安装到该索引路径的单元格中,假设它仍在屏幕上。如果一个单元格在可以加载之前在屏幕外滚动,那么你仍然可以从磁盘上的文件中加载它的数据,而不是重新下载它。

该方法只会加载可见的单元格,并且每个单元格都会显示为内容已完成加载,从而使屏幕更快地开始更新。

答案 1 :(得分:0)

排除加速服务器或缩小查询范围,获得计算节省的唯一其他方法是在用户更改类别时取消当前正在进行的请求。

为此,请将任务保留在属性中......

@property(strong,nonatomic) NSURLSessionDataTask *productTask;

然后在开始新帖子之前取消最后一篇文章(如果存在)...

[self.productTask cancel];
self.productTask = [self.manager POST:PRODUCT_URL parameters:params success:^(AFHTTPRequestOperation * _Nonnull operation, id responseObject) {
    // etc.

除此之外,还有一些UI技巧可以让用户对时间的感知更快。 (@DuncanC最好只加载可见行并重新加载,但是不清楚你可以在较小批量中获取它们)。其他一些想法是进度条,活动指标或kitten videos