0

I have a segmented control which looks like this:

enter image description here

With the following code in cellForRowAt:

switch cell.methodType.selectedSegmentIndex{
            case 0: expense.cash = true && expense.credit != true
            case 1: expense.credit = true && expense.cash != true
            default:
                break
            }

When I click on the other 3 columns, I select an option and I get directed back to this view controller which gets populated like below.

enter image description here

However, at random times, the segmented control can switch from credit to cash and I have to reselect credit. I ave no idea why this is happening. It happens sometimes, and doesn't happen others. Whenever this happens, my expense type switches from credit to cash and it doesn't register as credit. I have the following code in my cellForRowAt in another view controller where all the expenses get saved which looks like this:

 if expense.cash && expense.expense{
        print("cash")
        cell.cashOrCredit.image = #imageLiteral(resourceName: "Cash-Expense Icon")
    }
    else if expense.cash && expense.income{
        print("cash")
        cell.cashOrCredit.image = #imageLiteral(resourceName: "Cash-Income Icon")
    }
    else if expense.credit && expense.income{
        print("credit")
        cell.cashOrCredit.image = #imageLiteral(resourceName: "Credit-Income Icon")
    }
    else if expense.credit && expense.income{
        print("credit")
        cell.cashOrCredit.image = #imageLiteral(resourceName: "Credit-Expense Icon")
    }

If the segmented control doesn't change while I click the 3 other rows, then it registers as "credit", but if it randomly decides to change to cash, then the expense registers as "cash".

Here is the code for my whole cellForAtIndexPath

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

    let cell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath) as! ListDataTableViewCell

    if indexPath.row == 0{
        cell.dataTitleLabel.text = "Category"
        cell.methodType.isHidden = true
        cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
        cell.optionSelectedLabel.isHidden = false
        cell.optionSelectedLabel.text! = categoryDisplayed
        cell.optionSelectedLabel.adjustsFontSizeToFitWidth = true

    } else if indexPath.row == 1{
        cell.dataTitleLabel.text = "Method"
        cell.methodType.isHidden = false
        cell.methodType.tintColor = UIColor(red:0.29, green:0.68, blue:0.71, alpha:1.0)
        cell.optionSelectedLabel.isHidden = true
        cell.accessoryType = .none
        cell.selectionStyle = .none

    } else if indexPath.row == 2{
        cell.dataTitleLabel.text = "Currency"
        cell.methodType.isHidden = true
        cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
        cell.optionSelectedLabel.isHidden = false
        cell.optionSelectedLabel.text! = currencyDisplayed
        cell.optionSelectedLabel.adjustsFontSizeToFitWidth = true
        cell.optionSelectedLabel.minimumScaleFactor = 0.2

    } else if indexPath.row == 3{
        cell.dataTitleLabel.text = "Collection"
        cell.methodType.isHidden = true
        cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
        cell.optionSelectedLabel.isHidden = false
        cell.optionSelectedLabel.text! = collectionsDisplayed
        cell.optionSelectedLabel.adjustsFontSizeToFitWidth = true


    }
    return cell
}

I tried updating the code to this

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

    let cell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath) as! ListDataTableViewCell
    let cell2 = tableView.dequeueReusableCell(withIdentifier: "listCell2", for: indexPath) as! ListDataTableViewCell2

    if indexPath.row == 0{
        cell.dataTitleLabel.text = "Category"
        cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
        cell.optionSelectedLabel.isHidden = false
        cell.optionSelectedLabel.text! = categoryDisplayed
        cell.optionSelectedLabel.adjustsFontSizeToFitWidth = true
        return cell

    } else if indexPath.row == 1{
        cell2.dataLabel.text = "Method"
        cell2.methodType.isHidden = false
        cell2.methodType.tintColor = UIColor(red:0.29, green:0.68, blue:0.71, alpha:1.0)
        cell2.accessoryType = .none
        cell2.selectionStyle = .none
        return cell2

    } else if indexPath.row == 2{
        cell.dataTitleLabel.text = "Currency"
        cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
        cell.optionSelectedLabel.isHidden = false
        cell.optionSelectedLabel.text! = currencyDisplayed
        cell.optionSelectedLabel.adjustsFontSizeToFitWidth = true
        cell.optionSelectedLabel.minimumScaleFactor = 0.2
        return cell

    } else if indexPath.row == 3{
        cell.dataTitleLabel.text = "Collection"
        cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
        cell.optionSelectedLabel.isHidden = false
        cell.optionSelectedLabel.text! = collectionsDisplayed
        cell.optionSelectedLabel.adjustsFontSizeToFitWidth = true
        return cell
    }
    else {
        return cell
    }
}

but am greeted with a SIGABRT error in the line which declares the cell2

A. G
  • 631
  • 2
  • 9
  • 19
  • How you are saving the selected state - "Cash" or "Credit" - when the user taps the segmented control? – DonMag Dec 26 '17 at 15:23
  • In the first bit of code – A. G Dec 26 '17 at 15:41
  • You should save which index is selected somewhere else (for example in the viewController itself), and not in cell. Cells get reused, so you can not rely on data saved there. – Predrag Samardzic Dec 26 '17 at 16:09
  • Show your complete `cellForRowAt` implementation. The problem is there. – matt Dec 26 '17 at 17:42
  • It could be due to cell reuse but we really need to see more detail. How are you separating the data of the information from the UI implementation. Plus when you say 'random' what is actually being done at these 'random' times. – Upholder Of Truth Dec 26 '17 at 18:01
  • I have added the cellForRowAt code – A. G Dec 27 '17 at 03:17
  • @Did you self.tableView.register( forCellReuseIdentifier:) this new cell and set the new identifier in Storyboard/XIB? Did you set the correct type to the new cell in XIB/Storyboard and did you connect all outlets? – meaning-matters Dec 27 '17 at 08:10
  • @Did you `tableView.register( forCellReuseIdentifier:)` this new cell and set the new identifier in Storyboard/XIB? Did you duplicate the cell in InterfaceBuilder and did you set the correct type to the new cell in XIB/Storyboard. Did you connect all outlets? – meaning-matters Dec 27 '17 at 08:18

1 Answers1

2

The segmented control does not flip at random. I can tell you that this happens after you scroll the cell with the segment control far enough out of sight and back again.

When cells disappear from sight, they get reused for other cells that use the same cell identifier. And if you have a very long table, cells may also get deallocated.

Assuming that you don't have a very long table, my guess is that you don't have a dedicated cell identifier that you use just for the cell that has a segment control. If that's the case, try and give that segmented cell a unique identifier; the problem should disappear.

But that's not enough. Your segment cell could still get deallocated if it's out of sight (long/far enough). So you need to store the segment control selection somewhere in your view controller and set the selected segment in cellForRowAt. If you do this, there's no longer a need for a unique cell identifier.

Seeing your added code here are a few things:

  1. You must only get one of the two cells in cellForRowAt indexPath:, depending on indexPath. So you could place dequeueReusableCell inside the if blocks.
  2. You still don't set methodType's value (see my answer above).
  3. The term Type is confusing. According to rather common naming style, I'd call this methodSegmentControl (or methodSegment).
  4. Indeed, as you've done, it's typical to create two cell classes: ListDataTableViewCell and ListDataTableViewCell2. You can now get rid of the cell.methodType.isHidden = true/false, because only cell 2 needs the segment control.

I hope this helps and clears things up. Good luck!

It seems that you're lacking basic knowledge of how to work with tables and cells in iOS. I advise you to read through a good tutorial. I will save you a lot of time trying to figure it out by trial and error.

meaning-matters
  • 21,929
  • 10
  • 82
  • 142