uicollectionview update datasource




Как узнать, что UICollectionView полностью загружен? (8)

Def:

//Subclass UICollectionView
class MyCollectionView: UICollectionView {

    //Store a completion block as a property
    var completion: (() -> Void)?

    //Make a custom funciton to reload data with a completion handle
    func reloadData(completion: @escaping() -> Void) {
        //Set the completion handle to the stored property
        self.completion = completion
        //Call super
        super.reloadData()
    }

    //Override layoutSubviews
    override func layoutSubviews() {
        //Call super
        super.layoutSubviews()
        //Call the completion
        self.completion?()
        //Set the completion to nil so it is reset and doesn't keep gettign called
        self.completion = nil
    }

}

Затем вызовите это внутри вашего VC

let collection = MyCollectionView()

self.collection.reloadData(completion: {

})

Убедитесь, что вы используете подкласс !!

Я должен выполнить некоторую операцию всякий раз, когда UICollectionView был загружен полностью, то есть в это время все вызовы должны были вызываться все методы UatollectionView / datasource / layout. Откуда я знаю это? Есть ли какой-либо метод делегата, чтобы узнать статус загрузки UICollectionView?


Вот как я решил проблему с Swift 3.0:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if !self.collectionView.visibleCells.isEmpty {
        // stuff
    }
}

Как ответил dezinezync , вам нужно отправить в основную очередь блок кода после reloadData из UITableView или UICollectionView , а затем этот блок будет выполнен после деоклирования ячеек

Чтобы сделать это более прямым при использовании, я бы использовал расширение следующим образом:

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

Он также может быть реализован в UITableView


Мне нужно было какое-то действие для всех видимых ячеек, когда просмотр коллекции будет загружен до того, как он станет видимым для пользователя, я использовал:

public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if shouldPerformBatch {
        self.collectionView.performBatchUpdates(nil) { completed in
            self.modifyVisibleCells()
        }
    }
}

Обратите внимание, что это будет вызываться при прокрутке списка коллекций, поэтому, чтобы предотвратить эти накладные расходы, я добавил:

private var souldPerformAction: Bool = true

и в самом действии:

private func modifyVisibleCells() {
    if self.shouldPerformAction {
        // perform action
        ...
        ...
    }
    self.shouldPerformAction = false
}

Действие будет выполняться несколько раз, как количество видимых ячеек в исходном состоянии. но на всех этих вызовах у вас будет одинаковое количество видимых ячеек (все они). И логический флаг предотвратит его запуск после того, как пользователь начнет взаимодействовать с представлением коллекции.


Попробуй это:

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return _Items.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell;
    //Some cell stuff here...

    if(indexPath.row == _Items.count-1){
       //THIS IS THE LAST CELL, SO TABLE IS LOADED! DO STUFF!
    }

    return cell;
}

Просто добавьте отличный ответ @dezinezync:

Swift 3+

collectionView.collectionViewLayout.invalidateLayout() // or reloadData()
DispatchQueue.main.async {
    // your stuff here executing after collectionView has been layouted
}

Это работает для меня:

__weak typeof(self) wself= self;
[self.contentCollectionView performBatchUpdates:^{
    [wself.contentCollectionView reloadData];
} completion:^(BOOL finished) {
    [wself pageViewCurrentIndexDidChanged:self.contentCollectionView];
}];

Это сработало для меня:

[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
})