0
votes

I have a tableView that displays hidden cells when the user scrolls. Not sure why this behavior is happening.

In viewDidLoad()

    watchListTable = UITableView(frame: CGRect(x: self.view.frame.width * 0.25, y: 0, width: self.view.frame.width * 0.75, height: 300)) //height = 200
    watchListTable.isHidden = true
    watchListTableFrame = CGRect(x: self.view.frame.width * 0.25, y: 0, width: self.view.frame.width * 0.75, height: 300)
    watchListTableFrameHide = CGRect(x: self.view.frame.width * 0.25, y: 0, width: self.view.frame.width * 0.75, height: 0)
    watchListTable.register(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
    watchListTable.register(UITableViewCell.self, forCellReuseIdentifier: "closeCell")

    watchListTable.dataSource = self
    watchListTable.delegate = self
    watchListTable.CheckInterfaceStyle()
    watchListTable.roundCorners(corners: .allCorners, radius: 8)
    watchListTable.backgroundColor = .systemGray6
    //remove the bottom line if there is only one option
    watchListTable.tableFooterView = UIView()

    view.addSubview(watchListTable)

Once the user taps on a button, the table expands in an animatable fashion.

   //watchlist won't animate properly on the initial setup. So we set it to be 
    hidden, then change the frame to be 0,  unhide it, and then animate it. Only will 
    be hidden on the initial setup.
    if(watchListTable.isHidden == true)
    {
        watchListTable.isHidden = false
        watchListTable.frame = watchListTableFrameHide
    }
    
    UIView().animateDropDown(dropDown: watchListTable, frames: 
    self.watchListTableFrame)
    watchListTable.reloadData()

In func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

       if(indexPath.row >= watchListStocks.count)
        {
            let cell = tableView.dequeueReusableCell(withIdentifier: "closeCell", 
            for: indexPath as IndexPath)
            cell.selectionStyle = .none
            cell.textLabel?.text = indexPath.row == watchListStocks.count + 1 ? 
            "Close List" : "Create New Watchlist"
            cell.textLabel?.textColor = .stockOrbitTeal
            cell.textLabel?.textAlignment = .center
            cell.backgroundColor = .systemGray6
            cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 
            .greatestFiniteMagnitude)
           
            return cell                
        }
        else
        {
            let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: 
            indexPath as IndexPath)
            cell.selectionStyle = .none

            if(indexPath.row == 0)
            {
                cell.layer.cornerRadius = 8
                cell.layer.maskedCorners = [.layerMinXMinYCorner, 
                .layerMaxXMinYCorner]
            }
            else
            {
                cell.layer.cornerRadius = 8
                cell.layer.maskedCorners = [.layerMinXMaxYCorner, 
                .layerMaxXMaxYCorner]
                cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 
                .greatestFiniteMagnitude)
                cell.directionalLayoutMargins = .zero
            }
            
            let label = UITextView()
            
            label.frame = CGRect(x: 0, y: 0, width: cell.frame.width * 0.45, height: 
            cell.frame.height)
            label.text = watchListStocks[indexPath.row].listName
            label.textColor = .stockOrbitTeal
            label.textAlignment = .center
            label.font = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.medium)
            label.backgroundColor = .systemGray5
            label.delegate = self
            label.tag = indexPath.row
            cell.addSubview(label)
            
            cell.backgroundColor = .systemGray5
            cell.layer.cornerRadius = 8
            
            return cell
        }

When I scroll, all cells are hidden. I see that they are created in cellForRowAt, however, they do not appear on my screen. Why are the cells being hidden? I have searched all over stackoverflow.

2
This is probably totally irrelevant, but never say cell.addSubview. You can add to the contentView, not the cell.matt
thanks for that information! Changing the code now for that... Have you ever encountered a table disappearing when you scroll? This is so weird to me, and I can't seem to figure out why....Chris
The table is there, I can tap on the cells which I scroll. It's just not visible....Chris

2 Answers

1
votes
  1. You shouldn't add subviews inside cellForRowAt. When you call dequeueReusableCell, at first it'll create new cells, but when you start scrolling it'll start returning cells that were dismissed earlier, means they already have UITextView subview, and you're adding one more on top of that.

  2. cell returned by dequeueReusableCell doesn't have to have final size already, that's why you can't use cell.frame.width to calculate your subview size, I think that's may be the reason you can't see it.

What you need to do: create a UITableView subclass, something like this:

class MyCell: UITableViewCell {
    let label = UITextView()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupCell()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupCell()
    }
    
    func setupCell() {
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.medium)
        label.backgroundColor = .systemGray5
        contentView.addSubview(label)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        label.frame = CGRect(x: 0, y: 0, width: contentView.frame.width * 0.45, height: contentView.frame.height)
    }
}

Here you're adding a subview during initialisation only once and update label frame each time cell size gets changed. Don't forget to add this class to your cell in the storyboard and let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath as IndexPath) as! MyCell, so you can set delegate to text field, etc.

If this won't help, check out View Hierarchy to see what's actually going on there

0
votes

So after many hours, I figured it out...

I had called this function in viewDidLoad()

watchListTable.roundCorners(corners: .allCorners, radius: 8)

Which made my table hidden after I scrolled. I removed this line of code, and the table is now completely visible when scrolling.