首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有动画的集合视图滚动,导致图像位置错误

带有动画的集合视图滚动,导致图像位置错误
EN

Stack Overflow用户
提问于 2014-09-21 12:58:29
回答 3查看 428关注 0票数 1

我必须在集合视图中重新加载数据,以便根据新的数据源设置新的单元格大小。比我要滚动到开始,我想这样做的动画。每一行都有一个单元格。

因此,使用这个:

代码语言:javascript
运行
复制
    [self.collectionView reloadData];
    [self.collectionView setContentOffset:CGPointZero animated:YES];

发生的事情是,它滚动到开始,重新加载,但当他谈到图像1,比我看到许多图像替换得很快,它停在一些图像不是属于第一个单元,而是其他单元格。

如果我滚动到启动-没有动画(nimated:NO),它不会发生。我需要那个动画。是什么导致了这个问题?

编辑:我可以看到一个类似的问题,当我快速滚动时,我可以看到在它们的单元格中变化非常快的图像,然后再转到应该加载的最终图像。

EN

回答 3

Stack Overflow用户

发布于 2014-09-21 15:53:51

问题是细胞被重复使用,

所以让我们看看这个例子

代码语言:javascript
运行
复制
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"YourCellId"];
    cell.image = nil;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        UIImage *image = [self imageForIndexPathRow:@(indexPath.row)];
       dispatch_async(dispatch_get_main_queue(), ^{
           cell.image = image;
       });
    });
    return cell;
}  

由于操作是异步的,快速滚动将导致为一个单元分派两个操作。

例如,让我们将某些单元格指针命名为"ImageCell-1“。

现在让我们看看,如果您开始快速滚动,并且分派了两个操作,将会是什么样子的。

第一个操作加载"a.png",下载是活动的,您可以快速滚动,"ImageCell-1“现在正在加载"b.png”(但"a.png“仍在加载)。

因此,"a.png“完成下载并设置为"ImageCell-1",然后完成"b.png”并设置为"ImageCell-1“。

(这是一个问题,您可以看到=>“我可以看到一个类似的问题,当我快速滚动,我可以看到在他们的细胞中变化非常快的图像,然后他们转到应该加载的最终图像”)。

但也可以是情况(当您使用“高级库”(如AFNetworking )、队列由它们管理、并发下载可用时),"b.png“完成下载并将其设置为"ImageCell-1",然后完成"a.png”下载并设置为"ImageCell-1“。这将导致看到的是"a.png“而不是"b.png”。

解决方案是在启动新的下载操作之前取消下载操作,如果您使用的是AFNetworking,则保留NSOperations,并在开始新下载之前调用[operation cancelOperation];

编辑:

如果您正在使用NSURLConnection,则需要切换到使用NSURLSession的现代方式(以支持请求取消)。

这里我写了一个小方法,它解决了你的问题。

代码语言:javascript
运行
复制
@interface MyCell ()

@property (strong, nonatomic) NSURLSessionDataTask *dataTask;

@end

- (void)loadImageFromPath:(NSString *)aPath
           availableCache:(NSCache *)aCache
{
    if (self.dataTask) {
        [self.dataTask cancel];
    }

    NSData *cache = [aCache objectForKey:aPath];
    if (cache) {
        self.image = [UIImage imageWithData:cache];
        return;
    }
    self.dataTask = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:aPath]
                                      completionHandler:^(NSData *data,
                                                          NSURLResponse *response,
                                                          NSError *error)
                                {
                                    if (data) {
                                        self.image = [UIImage imageWithData:data];
                                        self.dataTask = nil;

                                        // Add to cache
                                        [aCache setObject:data forKey:aPath];
                                    }
                                }];
    [self.dataTask resume];
}

把这个方法放在你的细胞里,

cellForRow打电话来,就像这样

代码语言:javascript
运行
复制
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"YourCellId"];
    [cell loadImageFromPath:imagePath availableCache:self.cache];
    return cell;
} 
票数 1
EN

Stack Overflow用户

发布于 2014-09-21 19:49:05

我想我解决了这个问题,或者改进了很多东西。

那么,当您开始从网络下载时,给您的块一个标签:

代码语言:javascript
运行
复制
- (void)downloadImageWithURL:(NSURL *)url AndTag:(int)Gtag completionBlock:(void (^)(BOOL succeeded, NSData *data,int tag))completionBlock
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    int thetag=Gtag;
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
     {
         if (!error)
         {

             completionBlock(YES, data,thetag);
         }
         else
         {

             completionBlock(NO, nil,thetag);
         }
     }];
}

当下载完成时,我们将检查单元格现在是否在屏幕上,如果没有,我们将不会将其图像加载到单元格中:

代码语言:javascript
运行
复制
  [self downloadImageWithURL:url AndTag:(int)cell.tag  completionBlock:^(BOOL succeeded, NSData *data,int tag)
         {

     BOOL isvisible=0;
                 for (iPhoneCostumCell *tcell in [self.collectionView visibleCells])
                 {
                    if(tcell.tag==tag)
                    {
                        isvisible=1;
                        break;
                    }
                 }

我认为这是一个很好的解决方案,它使事情更加稳定。它也使处理器的工作效率降低,因为如果我们找不到图像,我们就不会继续在另一个线程中进行NSData转换。

票数 1
EN

Stack Overflow用户

发布于 2014-09-21 18:51:05

代码语言:javascript
运行
复制
[UIView animateWithDuration:1.0 delay:0.0 options: UIViewAnimationOptionCurveEaseIn animations:^{
        [self.collectionView setContentOffset:CGPointZero animated:NO];
    } completion:nil];
}];

试着制作你自己的动画。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25959438

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档