#ios #swift #uicollectionview
Вопрос:
Я добавил UICollectionView в качестве подвида в свой ViewController. Я также установил UIRefreshControl для UICollectionView, который применяет NSDiffableDataSourceSnapshot, когда я нажимаю для обновления. Анимация скачет при применении моментального снимка (обратите внимание, что это происходит, даже если заголовок панели навигатора невелик).
Вот соответствующие фрагменты кода
var collectionView: UICollectionView! = nil
var dataSource: UICollectionViewDiffableDataSource<Section, Item>! = nil
override func viewDidLoad() {
super.viewDidLoad()
let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout:
generateLayout())
view.addSubview(collectionView)
collectionView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
collectionView.backgroundColor = .systemGroupedBackground
self.collectionView = collectionView
collectionView.delegate = self
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(doSomething), for: .valueChanged)
collectionView.refreshControl = refreshControl
}
@objc func doSomething(refreshControl: UIRefreshControl) {
DispatchQueue.main.async {
var dataSourceSnapshot = NSDiffableDataSourceSnapshot<Section, Item>()
// add data
dataSource.apply(dataSourceSnapshot)
}
refreshControl.endRefreshing()
}
Есть ли какие-либо изменения, которые я могу внести, чтобы применить снимок без внезапного скачка?
Ответ №1:
К сожалению, инженеры Apple не могут должным образом решить эту проблему, начиная с iOS 6.
Короче говоря: вы не хотите, чтобы endRefreshing
во время просмотра прокрутки isTracking
. UIRefreshControl
изменяет contentInset
и contentOffset
представление прокрутки, и это всегда вызывало такие скачки.
Если у вас где-либо есть состояние сетевого запроса или любой другой флаг, указывающий на то, что загрузка продолжается, вы можете просто сделать:
@objc func doSomething(refreshControl: UIRefreshControl) {
loading = true
DispatchQueue.main.async {
var dataSourceSnapshot = NSDiffableDataSourceSnapshot<Section, Item>()
// add data
dataSourceSnapshot.appendSections([.test])
dataSourceSnapshot.appendItems([.test])
self.dataSource.apply(dataSourceSnapshot)
self.loading = false
}
}
override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !loading amp;amp; collectionView.refreshControl!.isRefreshing {
collectionView.refreshControl!.endRefreshing()
}
}
Мне не совсем нравятся loading
такие флаги, но это всего лишь пример. Надеюсь, у вас есть лучший источник истины, указывающий, продолжается ли еще какая-то «работа».
Я предполагаю, что может быть более приятный способ решения этой проблемы (путем исправления классов во время выполнения), но обычно для исследования требуется время. Интересно, удовлетворяет ли это решение вашим потребностям?