Reloading collection view inside a table view cell

2019-03-01 10:54发布

问题:

I am trying to implement a collection view inside each table view cell in a table view, but am having trouble getting the collection view to reload at the right time. It looks like the collection view reloads itself after all the table view cells have been loaded, not each time a new cell is dequeued to the table view as I'm trying to make it do.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("LWTableViewCell") as! LWTableViewCell

    cell.collectionView.delegate = self
    cell.collectionView.dataSource = self

    if dataIsReady == 1 {
        setIndex = indexPath.row
        print("in table view cellForRowAtIndexPath, setting setIndex at \(setIndex)")
        cell.collectionView.reloadData()
    }
    return cell
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    if dataIsReady == 1 {
        print("In collection view numberOfItemsInSection setIndex is \(setIndex)")
        return self.model.sets[setIndex].subsets!.count
    }
    else { return 0 }   
}

In terminal, I get the following:

in table view cellForRowAtIndexPath, setting setIndex at 0

in table view cellForRowAtIndexPath, setting setIndex at 1

in table view cellForRowAtIndexPath, setting setIndex at 2

In collection view numberOfItemsInSection setIndex is 2

In collection view numberOfItemsInSection setIndex is 2

In collection view numberOfItemsInSection setIndex is 2

whereas I would expect to see the following order of events (given that the collection view reload method is/should be called each time a new table view cell is dequeued).

in table view cellForRowAtIndexPath, setting setIndex at 0

In collection view numberOfItemsInSection setIndex is 0

in table view cellForRowAtIndexPath, setting setIndex at 1

In collection view numberOfItemsInSection setIndex is 1

in table view cellForRowAtIndexPath, setting setIndex at 2

In collection view numberOfItemsInSection setIndex is 2

Any suggestions on why this behavior is happening, and how to potentially fix it would be much appreciated!

I have looked through some other questions on the topic, and am aware there are some tutorials on the topic (e.g., https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell-in-swift/), but before starting to do things with a different approach, I'd like to understand why the above doesn't seem to work / what could be done to make it work.

回答1:

You cannot rely on the sequence of the calls. Currently you are trying to pass setIndex from the table view's cellForRowAtIndexPath to the collection view's delegate methods. A simple way to fix this is rather than using a single variable to pass the row number, instead pass it in the collection view's tag property. Then each collection view will know it's relevant row number. i.e.

In the table view's cellForRowAtIndexPath:

cell.collectionView.tag = indexPath.row

And then in the collection view's numberOfItemsInSection:

return self.model.sets[collectionView.tag].subsets!.count

Note also that you should not need to test dataIsReady in these methods. This code is only needed in the table view's tableView:numberOfRowsInSection:. When the data is not ready, it should return 0 (ie. no rows to display). Therefore the table view's cellForRowAtIndexPath will never be called, and since there are no rows, there are no collection views, so their numberOfItemsInSection will never be called.