Подтвердить что ты не робот

CellForItemAtIndexPath возвращает нуль после прокрутки силы, чтобы сделать ее видимой

Итак, я пытаюсь написать код, который прокручивает представление коллекции к определенному индексу, затем вытаскивает ссылку на ячейку и делает некоторую логику. Однако я заметил, что если эта ячейка не была видна до свитка, вызов cellForItemAtIndexPath будет возвращать нуль, в результате чего остальная часть моей логики завершится с ошибкой.

[_myView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index 
                                                     inSection:0] 
                atScrollPosition:UICollectionViewScrollPositionTop
                        animated:NO];

//Tried with and without this line, thinking maybe this would trigger a redraw
[_myView reloadData];

//returns nil if cell was off-screen before scroll
UICollectionViewCell *cell = 
  [_myView cellForItemAtIndexPath:
    [NSIndexPath indexPathForItem:index inSection:0]];

Есть ли какой-нибудь другой метод, который я должен вызвать, чтобы заставить cellForItemAtIndexPath вернуть что-то для ячейки, которая неожиданно появилась в виду в результате прокрутки, непосредственно предшествующей ей?

4b9b3361

Ответ 1

Основываясь на ваших комментариях, это похоже на то, что вы в конечном счете после этого - это кадр ячейки. Способ сделать это, не полагаясь на существование ячейки, - спросить макет вида коллекции:

NSIndexPath *indexPath = ...;
UICollectionViewLayoutAttributes *pose = [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
CGRect frame = pose.frame;

Ответ 2

Я понял решение на данный момент. Если я вызываю [myView layoutIfNeeded] сразу после моего вызова reloadData, но перед моей попыткой получить ячейку все работает нормально. В настоящий момент все ячейки кэшированы, поэтому доступ выполняется быстро, но я боюсь, что это может дать мне плохую производительность, если мне нужно загрузить из Интернета или внутренней базы данных, но мы увидим.

Ответ 3

Если вы хотите получить доступ к соте и увидеть ее на экране:

NSIndexPath *indexPath = ...;

[collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically | UICollectionViewScrollPositionCenteredHorizontally animated:NO];

UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];

if(cell == nil) {
    [collectionView layoutIfNeeded];
    cell = [collectionView cellForItemAtIndexPath:indexPath];
}

if(cell == nil) {
    [collectionView reloadData];
    [collectionView layoutIfNeeded];
    cell = [collectionView cellForItemAtIndexPath:indexPath];
}

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

Ответ 4

Решение hfossli работало для меня, поэтому я представил версию Swift ниже. В моем случае я не смог получить ссылку на пользовательский UICollectionViewCell, возможно, потому, что он не был виден. Я много пробовал, но так же, как сказал Шайбк, это единственное рабочее решение.

Swift 3:

  func getCell(_ indexPath: IndexPath) -> CustCell? {
    cView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.centeredHorizontally, animated: false)
    var cell = cView.cellForItem(at: indexPath) as? CustCell
    if cell == nil {
      cView.layoutIfNeeded()
      cell = cView.cellForItem(at: indexPath) as? CustCell
    }
    if cell == nil {
      cView.reloadData()
      cView.layoutIfNeeded()
      cell = cView.cellForItem(at: indexPath) as? CustCell
    }
    return cell
  }

использование:

let indexPath = IndexPath(item: index, section: 0)
cView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition(), animated: true)
if let cell = getCell(indexPath) {
      cell. <<do what you need here>>
    }