Jir*_*une 90 delegates reload uicollectionview
每当完全加载UICollectionView时,我必须做一些操作,即那时应该调用所有UICollectionView的数据源/布局方法.我怎么知道?是否有任何委托方法来了解UICollectionView加载状态?
小智 135
这对我有用:
[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{}
completion:^(BOOL finished) {
/// collection-view finished reload
}];
Run Code Online (Sandbox Code Playgroud)
Swift 4语法:
self.collectionView.reloadData()
self.collectionView.performBatchUpdates(nil, completion: {
(result) in
// ready
})
Run Code Online (Sandbox Code Playgroud)
Cul*_*SUN 61
// In viewDidLoad
[self.collectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// You will get here when the reloadData finished
}
- (void)dealloc
{
[self.collectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];
}
Run Code Online (Sandbox Code Playgroud)
dez*_*ync 25
它实际上非常简单.
例如,当您调用UICollectionView的reloadData方法或它的布局的invalidateLayout方法时,您将执行以下操作:
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
dispatch_async(dispatch_get_main_queue(), ^{
//your stuff happens here
//after the reloadData/invalidateLayout finishes executing
});
Run Code Online (Sandbox Code Playgroud)
为什么这样有效:
主线程(我们应该进行所有UI更新的地方)包含主队列,它本质上是串行的,即它以FIFO方式工作.所以在上面的例子中,调用了第一个块,reloadData
调用了我们的方法,然后是第二个块中的任何其他块.
现在主线程也是阻塞的.因此,如果你reloadData
需要3秒执行,第二个块的处理将被这些3推迟.
nik*_*ans 12
只是添加一个伟大的@dezinezync答案:
Swift 3+
collectionView.collectionViewLayout.invalidateLayout() // or reloadData()
DispatchQueue.main.async {
// your stuff here executing after collectionView has been layouted
}
Run Code Online (Sandbox Code Playgroud)
使用 RxSwift/RxCocoa 的另一种方法:
collectionView.rx.observe(CGSize.self, "contentSize")
.subscribe(onNext: { size in
print(size as Any)
})
.disposed(by: disposeBag)
Run Code Online (Sandbox Code Playgroud)
像这样做:
UIView.animateWithDuration(0.0, animations: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.collectionView.reloadData()
}, completion: { [weak self] (finished) in
guard let strongSelf = self else { return }
// Do whatever is needed, reload is finished here
// e.g. scrollToItemAtIndexPath
let newIndexPath = NSIndexPath(forItem: 1, inSection: 0)
strongSelf.collectionView.scrollToItemAtIndexPath(newIndexPath, atScrollPosition: UICollectionViewScrollPosition.Left, animated: false)
})
Run Code Online (Sandbox Code Playgroud)
尝试在 reloadData() 调用之后立即通过 layoutIfNeeded() 强制同步布局传递。似乎适用于 iOS 12 上的 UICollectionView 和 UITableView。
collectionView.reloadData()
collectionView.layoutIfNeeded()
// cellForItem/sizeForItem calls should be complete
completion?()
Run Code Online (Sandbox Code Playgroud)
到目前为止我发现的最好的解决方案是使用CATransaction
来处理完成。
斯威夫特 5:
CATransaction.begin()
CATransaction.setCompletionBlock {
// UICollectionView is ready
}
collectionView.reloadData()
CATransaction.commit()
Run Code Online (Sandbox Code Playgroud)
更新:上述解决方案似乎在某些情况下有效,而在某些情况下则无效。我最终使用了公认的答案,这绝对是最稳定且经过验证的方法。这是 Swift 5 版本:
private var contentSizeObservation: NSKeyValueObservation?
Run Code Online (Sandbox Code Playgroud)
contentSizeObservation = collectionView.observe(\.contentSize) { [weak self] _, _ in
self?.contentSizeObservation = nil
completion()
}
collectionView.reloadData()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
60134 次 |
最近记录: |