我必须在集合视图中重新加载数据,以便根据新的数据源设置新的单元格大小。比我要滚动到开始,我想这样做的动画。每一行都有一个单元格。
因此,使用这个:
[self.collectionView reloadData];
[self.collectionView setContentOffset:CGPointZero animated:YES];
发生的事情是,它滚动到开始,重新加载,但当他谈到图像1,比我看到许多图像替换得很快,它停在一些图像不是属于第一个单元,而是其他单元格。
如果我滚动到启动-没有动画(nimated:NO
),它不会发生。我需要那个动画。是什么导致了这个问题?
编辑:我可以看到一个类似的问题,当我快速滚动时,我可以看到在它们的单元格中变化非常快的图像,然后再转到应该加载的最终图像。
发布于 2014-09-21 15:53:51
问题是细胞被重复使用,
所以让我们看看这个例子
- (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的现代方式(以支持请求取消)。
这里我写了一个小方法,它解决了你的问题。
@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
打电话来,就像这样
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"YourCellId"];
[cell loadImageFromPath:imagePath availableCache:self.cache];
return cell;
}
发布于 2014-09-21 19:49:05
我想我解决了这个问题,或者改进了很多东西。
那么,当您开始从网络下载时,给您的块一个标签:
- (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);
}
}];
}
当下载完成时,我们将检查单元格现在是否在屏幕上,如果没有,我们将不会将其图像加载到单元格中:
[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转换。
发布于 2014-09-21 18:51:05
[UIView animateWithDuration:1.0 delay:0.0 options: UIViewAnimationOptionCurveEaseIn animations:^{
[self.collectionView setContentOffset:CGPointZero animated:NO];
} completion:nil];
}];
试着制作你自己的动画。
https://stackoverflow.com/questions/25959438
复制相似问题