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