UICollectionView 在调用 reloadData 时不会立即更新,而是在 30-60 秒后随机更新
Posted
技术标签:
【中文标题】UICollectionView 在调用 reloadData 时不会立即更新,而是在 30-60 秒后随机更新【英文标题】:UICollectionView doesn't update immediately when calling reloadData, but randomly after 30-60 seconds 【发布时间】:2013-02-11 00:37:14 【问题描述】:正如标题所暗示的,我的UICollectionView
在调用reloadData
后不会立即更新和显示单元格。相反,它似乎最终会在 30-60 秒后更新我的收藏视图。我的设置如下:
UICollectionView
添加到 Storyboard 中的视图控制器,同时为视图控制器和标准插座设置设置了 delegate
和 dataSource
numberOfSectionsInRow
和 cellForItemAtIndexPath
都已实现并引用原型单元和其中的 imageView
这是转到 Twitter 的代码,获取时间线,将其分配给变量,重新加载带有推文的表格视图,然后通过推文查找照片并重新加载带有这些项目的集合视图。
即使我注释掉显示图像的代码,它仍然没有改变任何东西。
SLRequest *timelineRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:timelineURL parameters:timelineParams];
[timelineRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
if(responseData)
JSONDecoder *decoder = [[JSONDecoder alloc] init];
NSArray *timeline = [decoder objectWithData:responseData];
[self setTwitterTableData:timeline];
for(NSDictionary *tweet in [self twitterTableData])
if(![tweet valueForKeyPath:@"entities.media"]) continue;
for(NSDictionary *photo in [[tweet objectForKey:@"entities"] objectForKey:@"media"])
[[self photoStreamArray] addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[photo objectForKey:@"media_url"], @"url",
[NSValue valueWithCGSize:CGSizeMake([[photo valueForKeyPath:@"sizes.large.w"] floatValue], [[photo valueForKeyPath:@"sizes.large.h"] floatValue])], @"size"
, nil]];
[[self photoStreamCollectionView] reloadData];
];
【问题讨论】:
你确定这不仅仅是因为在请求完成之前你没有调用 -reloadData 吗? (这需要时间)。 【参考方案1】:这是从后台线程调用 UIKit 方法的典型症状。如果您查看-[SLRequest performRequestWithHandler:]
documentation,它表示处理程序不保证它将在哪个线程上运行。
将您对reloadData
的调用封装在一个块中并将其传递给dispatch_async()
;还将dispatch_get_main_queue()
作为队列参数传递。
【讨论】:
你赢了!完全按照您所说的包装代码解决了这个问题。 UITableView 和 UICollectionView 之间是否存在根本区别,可以让 reloadData 在 UITableView 而不是 UICollectionView 上工作? @nullfox 很高兴它成功了!我不知道有什么区别,但如果有的话,很可能是不应该依赖的实现细节。唯一的做法是确保发送到任何 UIKit 对象的消息都在主线程上发送。 用你的简单修复解决了几个小时的调试问题!顺便说一句,同样的问题与 UITableView 有关。谢谢! @RyJ 很高兴为您提供帮助! @CarlVeazey 感谢提示“这是从后台线程调用 UIKit 方法的典型症状。”我正在从 NSNotificationCenter 重新加载 UICollectionView,它表现得很愚蠢。在 dispatch_async 中包装 reload 解决了它。【参考方案2】:您需要将更新分派到主线程:
dispatch_async(dispatch_get_main_queue(), ^
[self.photoStreamCollectionView reloadData];
);
或在 Swift 中:
dispatch_async(dispatch_get_main_queue(),
self.photoStreamCollectionView.reloadData()
)
【讨论】:
【参考方案3】:Apple 说:您不应该在插入或删除项目的动画块中间调用此方法。插入和删除会自动导致表的数据得到适当的更新。
面对:你不应该在任何动画中间调用这个方法(包括 UICollectionView 在滚动)。
所以,你可以:
[self.collectionView setContentOffset:CGPointZero animated:NO];
[self.collectionView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
或者标记确定没有任何动画,然后调用reloadData; 或
[self.collectionView performBatchUpdates:^
//insert, delete, reload, or move operations
completion:nil];
【讨论】:
以上是关于UICollectionView 在调用 reloadData 时不会立即更新,而是在 30-60 秒后随机更新的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView 在 UICollectionViewCells 上调用 setNeedsDisplay
同时在多个 UICollectionView 上调用 reloadData
在 UICollectionView 上调用 reloadData 后 contentSize 未更新
无法在 Swift 3 中调用非函数类型“UICollectionView”的值