TonyStark
TonyStark

Reputation: 96

UITableViewCell subviews are displaying outside of cell

In a section of my UITableView, there are 5 cells, three of which have been configured to expand/collapse to provide a more detailed view when selected. One of these cells shows a diagram of a number of small squares, which displays perfectly, until another cell is expanded, like this:

Working Cell

When the cell is collapsed, however, the subviews in the cell display in different cells, in different sections, like this:

enter image description here

and this:

enter image description here

To create the subviews in the cell, this is my code in the cellForRow method, which just uses an array of UIViews:

for vote in vote_array {
    cell.contentView.addSubview(vote as? UIView ?? UIView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0)))
            }

I tried removing all the subviews before I added them by doing this, but it doesn't change anything:

for subview in cell.contentView.subviews {
                subview.removeFromSuperview()
            }

Edit: This is inside a switch statement, but here is the relevant cell/case cellForRow:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.contentView.clipsToBounds = true
            cell.clipsToBounds = true
            let vote_array = getVoteArray()

            for subview in cell.contentView.subviews {
                subview.removeFromSuperview()
            }

            for case let vote as UIView in vote_array {
                cell.contentView.addSubview(vote)
            }

Edit: The core of getVoteArray:

func getVoteArray() -> NSMutableArray {
    var i = 0
    var x = 20
    var y = 4
    let blockViews : NSMutableArray = []
    for color in blocks {
        let block = UIView.init(frame: CGRect.init(x: x, y: y, width: 20, height: 20))
        block.backgroundColor = color as? UIColor
        blockViews.add(block)
        x = x + 24
        i = i + 1
        if i == num_blocks_per_row { i = 0; y = y + 24; x = 20 }
    }
    diagramHeight = y + 24
    return blockViews
}

I can't seem to figure out why the subviews are generating randomly all over the tableView.

Upvotes: 0

Views: 1295

Answers (3)

Eloy B.
Eloy B.

Reputation: 615

Try to implement unique ReuseIdentifiers for collapsed and expanded states.

If the cell is collapsed then don't load all those views in it by dequeuing a collapsedCell where the height of all those UIViews is either 0 or they are not added to subview.

If the cell is expanded than deque a expandedCell where the views are layed out as in the first screenshot.

After expanding and or collapsing call tableview.reloadData()

Upvotes: 1

TonyStark
TonyStark

Reputation: 96

Ended up adding

for case let cell as UITableViewCell in tableView.subviews {
    for subview in cell.contentView.subviews {
        if subview.tag == 115 {
            subview.removeFromSuperview()
        }
    }
}

to my didSelectRowAt method, after adding the tag when each view is created. I'm still not sure why the views were being added to different cells, but this got rid of them at least.

Upvotes: 1

Josh Homann
Josh Homann

Reputation: 16347

It used to be a long long time ago that UIViews clipped their children, but that hasn't been true for a very long time. If you want clipping on you need to either change UIView.clipsToBounds to true or use the underlying CALayer property maskToBounds.

cell.contentView.clipsToBounds = true

Or you can check the box in the storyboard/nib.

Upvotes: 0

Related Questions