Swift UITableViewCell shows data hidden by default

I have a seemingly random problem where some of the cells in mine are UITableView

showing data that should be hidden by default.

Explain hidden data.

This is a portfolio of stocks where you can click on a cell to expand it (and see this data). When it closes, the data is hidden again.

Here is a screenshot of the problem I ran into causing random cells to display this data by default.

enter image description here

On the screenshot above it there are cells "RUS.TO" and "CUB", which display hidden data.

This is where views and labels are created to be hidden:

// #Advanced data

    stockNameView.setTranslatesAutoresizingMaskIntoConstraints(false)
    stockNameView.hidden = true
    self.addSubview(stockNameView)

    purchasePriceView.setTranslatesAutoresizingMaskIntoConstraints(false)
    purchasePriceView.hidden = true
    self.addSubview(purchasePriceView)

    lastPriceView.setTranslatesAutoresizingMaskIntoConstraints(false)
    lastPriceView.hidden = true
    self.addSubview(lastPriceView)

    daysHeldView.setTranslatesAutoresizingMaskIntoConstraints(false)
    daysHeldView.hidden = true
    self.addSubview(daysHeldView)

      

The 8 labels that overlap are subspecies of the above representations.

As you can see, these 4 views are hidden by default. So I don't think the problem is with my cell class?

There is only one place in my code where I am setting the hidden value of these 4 UIViews to false.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("com.Stocks.portfolioCell", forIndexPath: indexPath) as! portfolioCell


    if indexPath.row % 2 == 0 {
        cell.backgroundColor = UIColor.whiteColor()
    } else {
        cell.backgroundColor = UIColor.formulaWhiteColor()
    }

    if selectedCellIndexPath == indexPath {
        cell.tickerLabel.textColor = UIColor.formulaBlueColor()
        cell.heightSeperator.hidden = false
        cell.stockNameView.hidden = false
        cell.purchasePriceView.hidden = false
        cell.lastPriceView.hidden = false
        cell.daysHeldView.hidden = false
        cell.endSeperator.hidden = false
        tableHeight.constant = tableHeight.constant+250
        self.scrollView.contentSize = CGSize(width:self.view.bounds.width, height: self.contentView.frame.height)
    }

    if lastCollapsing == true || currentCollapsing == true {
        cell.tickerLabel.textColor = UIColor.formulaDarkGrayColor()
        cell.heightSeperator.hidden = true
        cell.stockNameView.hidden = true
        cell.purchasePriceView.hidden = true
        cell.lastPriceView.hidden = true
        cell.daysHeldView.hidden = true
        cell.endSeperator.hidden = true
        lastCollapsing = false
        currentCollapsing = false
        tableHeight.constant = tableHeight.constant-250
        self.scrollView.contentSize = CGSize(width:self.view.bounds.width, height: self.contentView.frame.height)
    }

    if stocks.count > 0 {
        let formulaStock = stocks[indexPath.row]

        ticker = formulaStock.valueForKey("ticker") as! String!

        let fontAwesomeBlueAttribute = [NSForegroundColorAttributeName: UIColor.formulaBlueColor(), NSFontAttributeName: UIFont(name: "FontAwesome", size: 12)!]
        let fontAwesomeGreenAttribute = [NSForegroundColorAttributeName: UIColor.formulaGreenColor(), NSFontAttributeName: UIFont(name: "FontAwesome", size: 12)!]
        let latoBoldDarkGrayAttribute = [NSForegroundColorAttributeName: UIColor.formulaDarkGrayColor(), NSFontAttributeName: UIFont(name: "Lato-Bold", size: 12)!]
        if ticker != "CASH" {
            let tickerString = "  \(ticker)" as NSString
            var tickerAttributedString = NSMutableAttributedString(string: tickerString as String)
            tickerAttributedString.addAttributes(fontAwesomeBlueAttribute, range: tickerString.rangeOfString(""))
            tickerAttributedString.addAttributes(latoBoldDarkGrayAttribute, range: tickerString.rangeOfString("  \(ticker)"))
            cell.tickerLabel.attributedText = tickerAttributedString
        } else {
            let tickerString = "  \(ticker)" as NSString
            var tickerAttributedString = NSMutableAttributedString(string: tickerString as String)
            tickerAttributedString.addAttributes(fontAwesomeGreenAttribute, range: tickerString.rangeOfString(""))
            tickerAttributedString.addAttributes(latoBoldDarkGrayAttribute, range: tickerString.rangeOfString("  \(ticker)"))
            cell.tickerLabel.attributedText = tickerAttributedString
        }

        weight = formulaStock.valueForKey("weight") as! Float
        cell.weightLabel.text = "\(weight.roundTo(2))%"

        cell.filledWeightWidth.constant = CGFloat(weight/2)

        lastPrice = formulaStock.valueForKey("lastPrice") as! Float
        purchasePrice  = formulaStock.valueForKey("purchasePrice") as! Float
        percentDifference = ((lastPrice/purchasePrice)*100.00)-100


        if ticker == "CASH" {
            cell.changeLabel.text = ""
        } else if percentDifference > 0 {
            cell.changeLabel.text = ("+\(percentDifference.roundTo(2))%")
            cell.changeLabel.textColor = UIColor.formulaGreenColor()
        } else if percentDifference < 0 && percentDifference > -100 {
            cell.changeLabel.text = ("\(percentDifference.roundTo(2))%")
            cell.changeLabel.textColor = UIColor.formulaRedColor()
        } else if percentDifference == 0 {
            cell.changeLabel.text = ("\(percentDifference.roundTo(2))%")
            cell.changeLabel.textColor = UIColor.formulaGreenColor()
        } else {
            cell.changeLabel.text = "N/A"
            cell.changeLabel.textColor = UIColor.formulaDarkGrayColor()
        }

        cell.stockNameLabel.text = formulaStock.valueForKey("name") as! String!
        cell.purchasePriceLabel.text = "$\(purchasePrice)"
        cell.lastPriceLabel.text = "$\(lastPrice)"
        daysHeld = formulaStock.valueForKey("daysHeld") as! Int
        cell.daysHeldLabel.text = "\(daysHeld)"
    }

    cell.selectionStyle = UITableViewCellSelectionStyle.None
    return cell
}

      

But the section of code that sets hidden cell values ​​to false. It requires mine to selectedCellIndexPath

be equal to the current index that it is passing through cellForRowAtIndexPath

.

Here's where I am setting selectedCellIndexPath

:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.dequeueReusableCellWithIdentifier("com.Stocks.portfolioCell", forIndexPath: indexPath) as! portfolioCell
    if let selectedCellIndexPath = selectedCellIndexPath {
        if selectedCellIndexPath == indexPath {
            self.selectedCellIndexPath = nil
            currentCollapsing = true
            tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
        } else {
            lastCollapsing = true
            self.selectedCellIndexPath = indexPath
            tableView.reloadRowsAtIndexPaths([lastIndexPath], withRowAnimation: .None)
            tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
            self.lastIndexPath = indexPath
        }
    } else {
        selectedCellIndexPath = indexPath
        self.lastIndexPath = indexPath
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
    }
    tableView.beginUpdates()
    tableView.endUpdates()
}

      

Which should ever be when I click on a cell.

Every time I supply a UITableView with a new dataset, I also have to run the following line of code:

(menuTabBarController.viewControllers as! [Portfolio_ViewController])[1].selectedCellIndexPath = nil

      

Specifies selectedCellIndexPath

nil to avoid potential problems.

So why do some random cells display information that should be hidden by default?

When I tested this error, I was not using any cells. This way the selectedCellIndex should never have a value at this point.

+3


source to share


4 answers


When you reuse a cell, the old values ​​are still stored on it, so every time you use dequeueReusableCellWithIdentifier

you need to reset the defaults or the last values ​​still cached in it.

From Apple documentation:



The table covers the implementation of the data source tableView: cellForRowAtIndexPath: Always reset all content when reusing a cell.

+1


source


This is most likely caused by cell reuse - if a previously selected cell was used as hidden

unselected , its subview values do not change.

You can fix this by adding else

branch:



if selectedCellIndexPath == indexPath {
    ...
} else {
    // reset cell to non-selected state
    ...
}

      

+2


source


After getting the cell from, dequeueReusableCell

do it. Cleans the loading of unwanted data from the view and this also gives better performance.

let cell = userTable.dequeueReusableCell(withIdentifier: "users", for: indexPath)


for v in cell.subviews {
    v.removeFromSuperview()
}

      

0


source


As @chedabob mentioned in his comment. UITableViewCell will call prepareForReuse()

before reusing the cell. Reset your views and meaning in it. So, inside the tableviewcell class, override the methodprepareForReuse()

//Inside your UITableViewCell

override func prepareForReuse() {
       //Reset cell values here 
}

      

0


source







All Articles