Доступ к свойствам UIView в фоновом потоке - PullRequest
1 голос
/ 29 января 2020

Я пытаюсь прокрутить коллекцию CollectionView по первой ячейке после появления представления, а затем снова при каждом нажатии кнопки. Проблема в том, что collectionView не сгенерировал все свои ячейки ни в одной из функций жизненного цикла представления.

Мое решение состоит в том, чтобы запустить l oop в фоновом потоке, который проверяет, если collectionView.visibleCells.count > 0, и когда это так, вернуться в основной поток и прокрутить до первой ячейки. Тем не менее, я получаю сообщение об ошибке, в котором говорится, что я не должен получать доступ к visibleCells из основного потока, а приложение при этом загружается.

Как мне добиться этой функциональности в главном потоке или проверить количество ячеек в фоновом потоке?

private func scrollToFirst() {
    DispatchQueue.global(qos: .background).async { [weak self] in
        if (self != nil) {
            while(self!.collectionView.visibleCells.count != 0) {
                DispatchQueue.main.async { [weak self] in
                    self!.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true)
                }
            }
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 30 января 2020

Существует метод делегата willDisplay , который вызывается непосредственно перед отображением collectionViewCell. Если у вас ранее не было ячеек, и это вызывается, то вы знаете, что вы собираетесь go от нуля до более чем нуля.

0 голосов
/ 30 января 2020

Да, не делай этого. UIKit не является потокобезопасным, поэтому структуры данных объектов представления могут измениться из-под вас, когда вы попытаетесь просмотреть их из фоновых потоков.

Похоже, должен быть лучший способ справиться с этим чем ожидание появления клеток.

Если вы не можете найти более чистый способ сделать это, вы можете использовать объект Timer, который работает в основном потоке. Этот код может выглядеть примерно так:

private func scrollToFirst(afterDelay delay: Double = 0.2) {
    _ = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { 
        timer, [weak self] in
        guard strongSelf = self else {
          return
        }
        if strongSelf.collectionView.visibleCells.count != 0 {
          self!.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true)
        }
}

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

...