1

I have read through similar questions but I haven't been able to solve it. I have a tableview which has a custom cell with a button to add and remove a class. I created a custom delegate to save and remove the class, and to change the state of the button. Changing the state of the button works fine, but when I'm scrolling the buttons don't hold the state (I'm guessing is because I'm dequeuing the cells)

in my cell for row at index path i tried checking to change the state of the button:

let isInSchedule = self.isClassScheduled(classAttend, from: self.classesInSchedule!)
    if isInSchedule == true {
        cell.addRemoveButton.selected = true

    } else {
        cell.addRemoveButton.selected = false
    }

and here is my delegate method where I save or remove the class

 func indexOfClassSelectedWithButton(index: NSIndexPath, tableView:UITableView, and button: AddRemoveClass) {
    if let currentlySavedClasses = ManagedObjectsController.sharedInstance.getAllScheduledClasses() as? [ClassScheduled] {
    let classSelected = self.classes[index.section]
    switch button.selected {
    case true:
            for classItem in currentlySavedClasses {
                if classSelected.presentation?.title == classItem.presentation?.valueForKey("title") as? String {
                    ManagedObjectsController.sharedInstance.deleteScheduledClass(classItem)
                    button.selected = false
                }
            }
        break
    default:
        if let classSelectedBreakout = classSelected.breakout?.valueForKey("breakoutID") as? String {
            let canSave = self.isBreakoutAvailable(classSelectedBreakout, allClasses: currentlySavedClasses)
            if canSave {
                ManagedObjectsController.sharedInstance.createScheduledClass(from: classSelected)
                button.selected = true
            } else {
                NSNotificationCenter.defaultCenter().postNotificationName(timeConlictNotication, object: nil)
            }
        }
      break
    }
    }
}

it changes the button state but when I start scrolling up or down the buttons don't hold the state (I'm aware is probably because I'm revising my cell so it is taking any cell that it is available. Any help is greatly appreciated.

Also, I have my cell within my view controller in story board. Why is is that if i do cell = PresentationCell() all of the views in my cell are nil? Im just trying to not reuse the cell as my last solution.

Gama
  • 352
  • 2
  • 16
  • TableView cells do not maintain state. As you scroll, it will reuse existing cells that are no longer on the screen. You need to maintain state outside the cell, and set up each cell from scratch in `tableView:cellForRowAtIndexPath:`. – Michael Mar 10 '16 at 01:22
  • I need to not reuse the cells? is that what you mean? – Gama Mar 10 '16 at 01:24
  • 1
    No, you MUST reuse cells because that's how UITableView works. Since they will be reused, any state you need must be maintained outside of the cell. – Michael Mar 10 '16 at 03:00
  • Thank you! the trick was to do like you said, to maintain the state of the button outside the cell. I added a boolean property to the object populating the cell and based on that property I would set the state of the button. Thank you again – Gama Mar 10 '16 at 04:03

3 Answers3

3

Reusable table view cells do not keep the state so that to keep the button hold it's states you have to do an another check based on your condition when the cell will appear on the screen. My suggestion is implement

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if isInSchedule == true {
    cell.addRemoveButton.selected = true

} else {
    cell.addRemoveButton.selected = false
}

}

Another thing is remembering reset states of cell before using by implement "prepareForReuse" in your custom cell.

override func prepareForReuse() {

}

I hope this would be help.

HSG
  • 1,224
  • 11
  • 17
  • I added addRemoveButton.selected = false in the prepareForReuse method, and it gets called avery time I scrolled the view but the problem persists. – Gama Mar 10 '16 at 02:29
0

You should be doing two things

  1. Override "prepareForReuse" in your UITableViewCell subclass to reset the tableview cell to some default state
  2. in tableView:cellForRowAtIndexPath: will dequeu a re-usable cell. Since that cell is being re-used and may have already been associated with a different indexPath you have to re-configure it. In your case, you would set the state of the button to reflect the indexPath you are about to assign the cell to
habs93
  • 105
  • 2
  • 9
  • what do yo mean by "you would set the state of the button to reflect the indexPath you are about to assign the cell to"? I thought thats what I was doing when i check for isInSchedule variable (see my code in original post) – Gama Mar 10 '16 at 02:36
  • It looks like you are using core data. Is it possible your changed aren't being saved correctly? I haven't got that much experience with swift but it's possible the changes to you're making aren't persisting. – habs93 Mar 10 '16 at 03:13
0

The solution came from @Michael " any state you need must be maintained outside of the cell" since the tableView reuses the cells that are already created I had to add a property to the class Im populating the tableview with (I used a bool but it can be anything) and based on that property I set the state of the button in the method cellForRowAtIndexPath.

Gama
  • 352
  • 2
  • 16
  • this is correct...but the problem i see in this solution is when the cell is not visible in the screen, that cell is updating and call the method cellForRowAtIndexPath where you check the state of the button and set tu true... so how can solved this? – xhinoda Jul 27 '18 at 12:59
  • I SOLVED, check my answer here: https://stackoverflow.com/questions/32558003/button-action-in-custom-uitableviewcell-affects-other-cells#51561371 – xhinoda Jul 27 '18 at 15:48