[uicollectionview] UICollectionView가 완전히로드되었는지 어떻게 알 수 있습니까?

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 가 대답 했듯이 , 필요한 것은 reloadDataa UITableView또는 에서 코드 블록을 메인 큐에 디스패치하는 UICollectionView것입니다. 그러면이 블록은 셀 대기열에서 제외 된 후에 실행됩니다.

사용할 때 이것을 더 똑바로 만들기 위해 다음과 같은 확장을 사용합니다.

extension UICollectionView {
    func reloadData(_ completion: @escaping () -> Void) {
        reloadData()
        DispatchQueue.main.async { completion() }
    }
}

그것은 또한에 구현 될 수 UITableView뿐만 아니라