Удаление N элементов из раздела просмотра коллекции предотвращает повторную загрузку последних N элементов в одном пакет ⇐ IOS
-
Гость
Удаление N элементов из раздела просмотра коллекции предотвращает повторную загрузку последних N элементов в одном пакет
Изменить: при дальнейшем тестировании обновление на iOS 15.2 не выполняется, но выполняется на iOS 13.0 и 14.0, так что, похоже, это ошибка iOS!
Я пытаюсь применить пакетные обновления к UICollectionView, но обнаруживаю, что для каждого удаленного элемента N в разделе N элементы в конце раздела будут игнорировать любые перезагрузки.
У меня есть пример UICollectionView:
импортировать UIKit последний класс CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { переменные данные: [[String]] = [] var RequestIndexPaths: [IndexPath] = [] переопределить функцию viewDidLoad() { супер.viewDidLoad() CollectionView.backgroundColor = .systemBackground CollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell") применитьInitialData( [ ["0, 0", "0, 1", "0, 2", "0, 3", "0, 4", "0, 5", "0, 6", "0, 7"], ] ) пусть обновитьControl = UIRfreshControl() обновитьControl.addTarget(self, действие: #selector(reloadAll), для: .valueChanged) CollectionView.refreshControl = RefreshControl } @objc частная функция reloadAll() { коллекцияView.reloadData() CollectionView.refreshControl?.endRefreshing() } func applyInitialData(_ data: [[String]]) { self.data = данные загрузитьViewIfNeeded() коллекцияView.reloadData() CollectionView.layoutIfNeeded() RequestIndexPaths = [] } переопределить func CollectionView (_ CollectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { RequestIndexPaths.append(indexPath) let cell = CollectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", для: indexPath) cell.contentView.subviews.forEach { $0.removeFromSuperview() } пусть метка = UILabel() label.text = данные[indexPath.section][indexPath.row] cell.contentView.addSubview(метка) label.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ label.topAnchor.constraint(equalTo: cell.topAnchor), label.leadingAnchor.constraint(equalTo: cell.leadingAnchor), ]) возвратная ячейка } переопределить функцию NumberOfSections (в CollectionView: UICollectionView) -> Int { data.count } переопределить func CollectionView (_ CollectionView: UICollectionView, раздел NumberOfItemsInSection: Int) -> Int { данные[раздел].count } func CollectionView (_ CollectionView: UICollectionView, макет CollectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { вернуть CGSize (ширина: CollectionView.frame.size.width, высота: 40) } переопределить func CollectionView (_ CollectionView: UICollectionView, DidSelectItemAt: IndexPath) { updateUsingReload() // обновлениеUsingInsertAndDelete() } /// С помощью этого метода 0, 6 не будут обновляться, пока не будет использовано обновление по запросу. частная функция updateUsingReload() { CollectionView.performBatchUpdates({ data[0][0] = "0, 0 (обновлено)" data[0][1] = "0, 1 (обновлено)" data[0][4] = "0, 4 (обновлено)" data[0][5] = "0, 5 (обновлено)" data[0][6] = "0, 6 (обновлено)" данные[0].удалить(в: 3) данные[0].удалить(в: 2) CollectionView.deleteItems(at: [ IndexPath(элемент: 2, раздел: 0), IndexPath(элемент: 3, раздел: 0), ]) CollectionView.reloadItems(at: [ IndexPath(элемент: 0, раздел: 0), IndexPath(элемент: 1, раздел: 0), IndexPath(элемент: 4, раздел: 0), IndexPath(элемент: 5, раздел: 0), IndexPath(элемент: 6, раздел: 0), ]) }) } /// При использовании этого метода все ячейки будут перезагружены, но анимация будет не такой /// приятно, потому что ячейки на самом деле не удаляются. частная функция updateUsingInsertAndDelete() { CollectionView.performBatchUpdates({ data[0][0] = "0, 0 (обновлено)" data[0][1] = "0, 1 (обновлено)" data[0][4] = "0, 4 (обновлено)" data[0][5] = "0, 5 (обновлено)" data[0][6] = "0, 6 (обновлено)" данные[0].удалить(в: 3) данные[0].удалить(в: 2) CollectionView.deleteItems(at: [ IndexPath(элемент: 2, раздел: 0), IndexPath(элемент: 3, раздел: 0), IndexPath(элемент: 4, раздел: 0), IndexPath(элемент: 5, раздел: 0), IndexPath(элемент: 6, раздел: 0), ]) CollectionView.insertItems(at: [ // 2 элемента действительно были удалены, для этих элементов используется "после" // индексы и равны 4, 5 и 6 до обновления. IndexPath(элемент: 2, раздел: 0), IndexPath(элемент: 3, раздел: 0), IndexPath(элемент: 4, раздел: 0), ]) CollectionView.reloadItems(at: [ IndexPath(элемент: 0, раздел: 0), IndexPath(элемент: 1, раздел: 0), ]) }) } } Когда я касаюсь ячейки (чтобы вызвать обновления), ячейка 0, 6 не обновляется. Вместо этого использование функции updateUsingInsertAndDelete перезагружает все ячейки, но нет анимации удаления, как при использовании updateUsingReload.
Этот пример есть в полном проекте https://github.com/JosephDuffy/CollectionViewTesting.
Изменить: при дальнейшем тестировании обновление на iOS 15.2 не выполняется, но выполняется на iOS 13.0 и 14.0, так что, похоже, это ошибка iOS!
Я пытаюсь применить пакетные обновления к UICollectionView, но обнаруживаю, что для каждого удаленного элемента N в разделе N элементы в конце раздела будут игнорировать любые перезагрузки.
У меня есть пример UICollectionView:
импортировать UIKit последний класс CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { переменные данные: [[String]] = [] var RequestIndexPaths: [IndexPath] = [] переопределить функцию viewDidLoad() { супер.viewDidLoad() CollectionView.backgroundColor = .systemBackground CollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell") применитьInitialData( [ ["0, 0", "0, 1", "0, 2", "0, 3", "0, 4", "0, 5", "0, 6", "0, 7"], ] ) пусть обновитьControl = UIRfreshControl() обновитьControl.addTarget(self, действие: #selector(reloadAll), для: .valueChanged) CollectionView.refreshControl = RefreshControl } @objc частная функция reloadAll() { коллекцияView.reloadData() CollectionView.refreshControl?.endRefreshing() } func applyInitialData(_ data: [[String]]) { self.data = данные загрузитьViewIfNeeded() коллекцияView.reloadData() CollectionView.layoutIfNeeded() RequestIndexPaths = [] } переопределить func CollectionView (_ CollectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { RequestIndexPaths.append(indexPath) let cell = CollectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", для: indexPath) cell.contentView.subviews.forEach { $0.removeFromSuperview() } пусть метка = UILabel() label.text = данные[indexPath.section][indexPath.row] cell.contentView.addSubview(метка) label.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ label.topAnchor.constraint(equalTo: cell.topAnchor), label.leadingAnchor.constraint(equalTo: cell.leadingAnchor), ]) возвратная ячейка } переопределить функцию NumberOfSections (в CollectionView: UICollectionView) -> Int { data.count } переопределить func CollectionView (_ CollectionView: UICollectionView, раздел NumberOfItemsInSection: Int) -> Int { данные[раздел].count } func CollectionView (_ CollectionView: UICollectionView, макет CollectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { вернуть CGSize (ширина: CollectionView.frame.size.width, высота: 40) } переопределить func CollectionView (_ CollectionView: UICollectionView, DidSelectItemAt: IndexPath) { updateUsingReload() // обновлениеUsingInsertAndDelete() } /// С помощью этого метода 0, 6 не будут обновляться, пока не будет использовано обновление по запросу. частная функция updateUsingReload() { CollectionView.performBatchUpdates({ data[0][0] = "0, 0 (обновлено)" data[0][1] = "0, 1 (обновлено)" data[0][4] = "0, 4 (обновлено)" data[0][5] = "0, 5 (обновлено)" data[0][6] = "0, 6 (обновлено)" данные[0].удалить(в: 3) данные[0].удалить(в: 2) CollectionView.deleteItems(at: [ IndexPath(элемент: 2, раздел: 0), IndexPath(элемент: 3, раздел: 0), ]) CollectionView.reloadItems(at: [ IndexPath(элемент: 0, раздел: 0), IndexPath(элемент: 1, раздел: 0), IndexPath(элемент: 4, раздел: 0), IndexPath(элемент: 5, раздел: 0), IndexPath(элемент: 6, раздел: 0), ]) }) } /// При использовании этого метода все ячейки будут перезагружены, но анимация будет не такой /// приятно, потому что ячейки на самом деле не удаляются. частная функция updateUsingInsertAndDelete() { CollectionView.performBatchUpdates({ data[0][0] = "0, 0 (обновлено)" data[0][1] = "0, 1 (обновлено)" data[0][4] = "0, 4 (обновлено)" data[0][5] = "0, 5 (обновлено)" data[0][6] = "0, 6 (обновлено)" данные[0].удалить(в: 3) данные[0].удалить(в: 2) CollectionView.deleteItems(at: [ IndexPath(элемент: 2, раздел: 0), IndexPath(элемент: 3, раздел: 0), IndexPath(элемент: 4, раздел: 0), IndexPath(элемент: 5, раздел: 0), IndexPath(элемент: 6, раздел: 0), ]) CollectionView.insertItems(at: [ // 2 элемента действительно были удалены, для этих элементов используется "после" // индексы и равны 4, 5 и 6 до обновления. IndexPath(элемент: 2, раздел: 0), IndexPath(элемент: 3, раздел: 0), IndexPath(элемент: 4, раздел: 0), ]) CollectionView.reloadItems(at: [ IndexPath(элемент: 0, раздел: 0), IndexPath(элемент: 1, раздел: 0), ]) }) } } Когда я касаюсь ячейки (чтобы вызвать обновления), ячейка 0, 6 не обновляется. Вместо этого использование функции updateUsingInsertAndDelete перезагружает все ячейки, но нет анимации удаления, как при использовании updateUsingReload.
Этот пример есть в полном проекте https://github.com/JosephDuffy/CollectionViewTesting.
Мобильная версия