简体   繁体   中英

Why is my custom collection view cell unexpectedly nil after selecting cell in code?

So I have a colectionView of images, and when something happens in the background, I might try to select a specific custom collectionViewCell using the method:

self.collectionView.selectItemAtIndexPath(indexPathToReload, animated: true, scrollPosition: UICollectionViewScrollPosition.CenteredVertically) , which works fine, the collectionView scrolls to the desired location.

However, if I then try to actually update the appearance of the cell as it's been updated by calling self.collectionView(self.collectionView, didSelectItemAtIndexPath: indexPathToReload) I get an unexpectedly nil cell when I then try to create the cell in didSelectItemAtIndexPath .

I partially understand why this method of updating cells is unsafe (as I've read elsewhere in researching this question like here in one of the answers .)

Thus, the crash makes me assume that cells are not part of the visible cells on the screen, which is why the cell is nil when I try to create it. But this doesn't make sense as I also assume that the cells have to be created in order to be scrolled to, which as I said works fines because they are created as expected and can be interacted with without issue.

So why is my cell nil? Or why is my collection view not thinking that the cell that was scrolled to not part of the visible cells? And if the reason is obvious, then how can I make a cell update it's appearance when I select it in code?

EDIT: Code in context

dispatch_async(dispatch_get_main_queue()) {
    self.collectionView.selectItemAtIndexPath(indexPathToReload, animated: true, scrollPosition: UICollectionViewScrollPosition.CenteredVertically)
    self.collectionView(self.collectionView, didSelectItemAtIndexPath: indexPathToReload)
    return
}

As I've said, this pretty much is the context. In the first line I may scroll to an index that is not visible on the screen. If I do this, and then the second line of code executes, the cell that is created in the delegate method that is called is unexpectedly nil.

In order to fix this issue, I had to use kind of a hacky workaround, which although works seems almost too dirty, and I don't know why this issue hasn't been addressed by Apple (ie why selectItemAtIndexPath doesn't call the delegate method didSelectItemAtIndexPath ). Anyways, what I ended up doing was when I needed to update my selected cell in background, I first got the index and set a bool to show a cell was selected in code:

dispatch_async(dispatch_get_main_queue()) {
    self.collectionView.selectItemAtIndexPath(indexPathToReload, animated: true, scrollPosition: UICollectionViewScrollPosition.CenteredVertically)
    let cell = self.collectionView.cellForItemAtIndexPath(indexPathToReload) as? ListingCollectionViewCell
    if cell != nil {
        self.collectionView(self.collectionView, didSelectItemAtIndexPath: indexPathToReload)
        return
    } else {
        self.buttonSelectedInCode = true
        self.indexPathSelectedInCode = indexPathToReload
        return
    }
}

Above, I had to try to create the cell for the specified index path. If the cell isn't nil then I know that the cell is visible, and it's safe to call on the delegate didSelectItemAtIndexPath . However, if the cell is nil, then I have to set up my bool and index, and wait for the scroll view to call the delegate method, as shown below.

Then, I further implemented scrollViewDidEndScrollAnimation and used the call of this delegate method to then select my cell in code, as follows:

func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
    if buttonSelectedInCode {
        self.collectionView(self.collectionView, didSelectItemAtIndexPath: self.indexPathSelectedInCode)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM