UICollectionView가 완전히로드 될 때마다 몇 가지 작업을 수행해야합니다. 즉, 이때 모든 UICollectionView의 데이터 소스 / 레이아웃 메서드를 호출해야합니다. 그것을 어떻게 압니까 ?? UICollectionView로드 상태를 알 수있는 대리자 메서드가 있습니까?
답변
// 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];
}
답변
이것은 나를 위해 일했습니다.
[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{}
completion:^(BOOL finished) {
/// collection-view finished reload
}];
Swift 4 구문 :
self.collectionView.reloadData()
self.collectionView.performBatchUpdates(nil, completion: {
(result) in
// ready
})
답변
실제로는 매우 간단합니다.
예를 들어 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
});
이것이 작동하는 이유 :
기본 스레드 (모든 UI 업데이트를 수행해야하는 곳)에는 본질적으로 직렬 인 기본 대기열이 있습니다. 즉, FIFO 방식으로 작동합니다. 따라서 위의 예에서 첫 번째 블록이 호출 reloadData
되고 메서드가 호출되고 두 번째 블록의 다른 항목이 이어집니다.
이제 주 스레드도 차단됩니다. 따라서 reloadData
실행 하는 데 3 초가 걸리면 두 번째 블록의 처리가 해당 3 초에 의해 지연됩니다.
답변
훌륭한 @dezinezync 답변에 추가하려면 다음을 수행하십시오.
Swift 3+
collectionView.collectionViewLayout.invalidateLayout() // or reloadData()
DispatchQueue.main.async {
// your stuff here executing after collectionView has been layouted
}
답변
다음과 같이하십시오.
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)
})
답변
reloadData () 호출 직후 layoutIfNeeded ()를 통해 동기식 레이아웃 전달을 시도하십시오. iOS 12에서 UICollectionView 및 UITableView 모두에서 작동하는 것 같습니다.
collectionView.reloadData()
collectionView.layoutIfNeeded()
// cellForItem/sizeForItem calls should be complete
completion?()
답변
dezinezync 가 대답 했듯이 , 필요한 것은 reloadData
a UITableView
또는 에서 코드 블록을 메인 큐에 디스패치하는 UICollectionView
것입니다. 그러면이 블록은 셀 대기열에서 제외 된 후에 실행됩니다.
사용할 때 이것을 더 똑바로 만들기 위해 다음과 같은 확장을 사용합니다.
extension UICollectionView {
func reloadData(_ completion: @escaping () -> Void) {
reloadData()
DispatchQueue.main.async { completion() }
}
}
그것은 또한에 구현 될 수 UITableView
뿐만 아니라