6

Я пытаюсь найти лучший способ обработки состояния для UICollectionView, элементы которого могут перемещаться. Моя цель - убедиться, что последний просматриваемый элемент в представлении коллекции все еще отображается при перезапуске приложения, даже если элементы перемещены. Например, элемент A находится в ячейке по индексу 3, когда приложение было убито, и когда приложение перезапустится, если в модели указано, что элемент A должен отображаться в индексе 4, я хочу, чтобы представление коллекции инициализировало смещение в ячейке по индексу 4.Восстановление состояния UICollectionView: настройка положения прокрутки

Я думал, что реализация протокола UIDataSourceModelAssociation в моем UICollectionViewDataSource классе будет заботиться об этом для меня, как documentation состояний:

[UITableView и UICollectionView] классы используют методы этого протокола для обеспечения что одни и те же объекты данных (а не только одни и те же индексы строк) прокручиваются в окно просмотра и выбираются.

Однако то, что я наблюдал, что осуществление этого протокола делает правильно влияет на indexPath из выбранных ячеек во время восстановления (не важно мое приложение), но это не влияет на позицию прокрутки. Позиция прокрутки (contentOffset представления коллекции) всегда восстанавливается точно там, где это было, когда приложение было убито и не затронулось UICollectionViewDataSource.

У меня есть обходное решение, которое выглядит так. Это в основном по той же схеме, как протокол Assocation модели, но я должен сделать это вручную:

override func encodeRestorableStateWithCoder(coder: NSCoder) { 
    let identifier = determineIdOfCurrentlyVisibleCell() 
    coder.encodeObject(identifier, forKey: "visibleCellIdentifier") 
} 

override func decodeRestorableStateWithCoder(coder: NSCoder) { 
    if let identifier = coder.decodeObjectForKey("visibleCellIdentifier") as? String { 
     if let indexPath = model.indexPathForIdentifier(identifier) { 
      collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredVertically, animated: false) 
     } 
    } 
} 

ли я неправильно использование UIDataSourceModelAssociation? Есть ли ошибка? Есть ли более элегантный или правильный способ заставить это работать?

+0

Как я могу видеть 'indexPathForElementWithModelIdentifier: INview:' разработано, чтобы сделать то же самое. Оно работает? – orkenstein

+0

@orkenstein Я попытался использовать это, но это не сработало. См. Мой OP: «реализация этого протокола правильно влияет на indexPath выбранных ячеек во время восстановления (что не важно для моего приложения), но это не влияет на положение прокрутки». –

ответ

5

Как вы уже указывали, UIDataSourceModelAssociation, похоже, не работает с восстановлением видимого смещения UICollectionView, но только для выбранных предметов. Я попытался установить контрольные точки на modelIdentifierForElementAtIndexPath и indexPathForElementWithModelIdentifier и заметил, что они были вызваны только после того, как я выбрал ячейку. Если я очистил выбранные ячейки коллекции, прежде чем устанавливать свое приложение, то modelIdentifierForElementAtIndexPath не будет вызван, но однажды я установил хотя бы одну ячейку. По крайней мере, я могу проверить, что вы не единственный, кто видит это поведение.

Я думаю, что из-за различной природы UICollectionView, вероятно, не просто создать поведение, которое прокручивает видимые ячейки до правильной точки, но это явно не отражено в документации Apple. Хорошей альтернативой должна быть ручная кодировка идентификатора первой видимой ячейки для вашего макета. То, что я делаю это обертывание смещения в NSValue и восстановлении, что прокрутить вид коллекции:

var collectionView: UICollectionView? 

// ... 

override func encodeRestorableStateWithCoder(coder: NSCoder) { 
    if let view = collectionView, offsetValue = NSValue(CGPoint: view.contentOffset) { 
     coder.encodeObject(offsetValue, forKey: CollectionViewContentOffsetKey) 
    } 

    super.encodeRestorableStateWithCoder(coder) 
} 

override func decodeRestorableStateWithCoder(coder: NSCoder) { 
    if let offsetValue = coder.decodeObjectForKey(CollectionViewContentOffsetKey) as? NSValue { 
     collectionView?.setContentOffset(offsetValue.CGPointValue(), animated: false) 
    } 

    super.decodeRestorableStateWithCoder(coder) 
} 
+1

Хороший анализ. Имеет смысл для меня. –

+0

Это сработало, но немного восстанавливало смещение в неправильном месте - что-то не так с вычислениями navigationBar. – soprof

Смежные вопросы