Programmatically moving UITableViewCell fails if manually moved first - ios

I have a UITableView containing custom cells. These cells are able to be manually moved. In addition, a switch on the cell causes it to be moved to the bottom. The switch works fine if it is used separately from drag-to-reorder. However, if I drag-to-reorder first, then use a switch, I get the following error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
The controller has the following code relating to the table:
//Table Delegate/Datasource
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
let object = self.eventTypes[sourceIndexPath.row]
self.eventTypes.insertObject(object, atIndex: sourceIndexPath.row)
self.eventTypes.removeObject(sourceIndexPath.row)
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.None
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:S360SEventTypeTableCell? = tableView.dequeueReusableCellWithIdentifier(XIBFiles.EVENTTYPETABLECELL) as? S360SEventTypeTableCell
if ((cell == nil)){
tableView.registerNib(UINib(nibName: XIBFiles.EVENTTYPETABLECELL, bundle: nil), forCellReuseIdentifier: XIBFiles.EVENTTYPETABLECELL)
cell = tableView.dequeueReusableCellWithIdentifier(XIBFiles.EVENTTYPETABLECELL) as? S360SEventTypeTableCell
}
let eventType = eventTypes[indexPath.row]
cell!.iconImg.image = Images.get_event_image(eventType["title"]! as! String)
cell!.titleLbl.text = (eventType["title"]! as! String)
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventTypes.count
}
The custom cell has the following code:
#IBOutlet var iconImg:UIImageView!
#IBOutlet var titleLbl:UILabel!
#IBOutlet var timeField:UITextField!
#IBOutlet var activeSwtch:UISwitch!
#IBOutlet var durationLbl:UILabel!
#IBOutlet var minsLbl:UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
override func layoutSubviews() {
super.layoutSubviews()
//Styling
timeField.layer.borderColor = Colors.REALLIGHTGREY.CGColor
timeField.layer.borderWidth = Numbers.BORDERREG
timeField.layer.cornerRadius = Numbers.CORNERRADIUS
timeField.tintColor = Colors.REDNESS
activeSwtch.onTintColor = Colors.REDNESS
self.showsReorderControl = true
}
func getTableView() -> UITableView?{
var tableView:UITableView? = nil
var view:UIView = self
while !view.isKindOfClass(UITableView.self) && view.superview != nil {
view = view.superview!
}
if view.isKindOfClass(UITableView.self) {
tableView = (view as! UITableView)
}
return tableView
}
#IBAction func activeSwtchTouch(){
if self.activeSwtch.on{
self.titleLbl.enabled = true
self.timeField.enabled = true
self.durationLbl.enabled = true
self.minsLbl.enabled = true
self.iconImg.alpha = 1.0
self.showsReorderControl = true
}
else{
let tableView = self.getTableView()
if tableView != nil {
let fromPath = tableView!.indexPathForCell(self)!
let toPath = NSIndexPath(forRow: tableView!.numberOfRowsInSection(fromPath.section) - 1, inSection: fromPath.section)
print("FROM: " + String(fromPath.row) + ":" + String(fromPath.section))
print("TO: " + String(toPath.row) + ":" + String(toPath.section))
print("SECTIONS: " + String(tableView!.numberOfSections))
print("ROWS: " + String(tableView!.numberOfRowsInSection(fromPath.section)))
tableView!.moveRowAtIndexPath(fromPath, toIndexPath: toPath)
self.titleLbl.enabled = false
self.timeField.enabled = false
self.durationLbl.enabled = false
self.minsLbl.enabled = false
self.iconImg.alpha = 0.5
self.showsReorderControl = false
}
}
}
Of Note: The custom delegate method for moveRowAtIndexPath seems to only be called when drag-to-reorder is used, but not when the UISwitch touch triggers. At the very least, the breakpoints in that method do not get hit when UISwitch touch trigger is used.

Dumb mistake. This line self.eventTypes.removeObject(sourceIndexPath.row) should be self.eventTypes.removeObject(object). The object was never being removed, and therefore, when a reload or update finishing was being called, it was not able to determine properly the amount of items, since it was growing with each move.

Related

When I tapped segment Odd or even I am getting true and false value in Tableview instead of odd value or even value

When I press odd it shows true or false. How can Get values of array I'm trying to print odd value when i tap odd on segment or even values when i tap even , How can get this. I'm new in ios. Please help
class ViewController: UIViewController, UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var segmentOutlet: UISegmentedControl!
let numberArray = Array(1...100)
var segmentIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.delegate = self
tableView.dataSource = self
}
#IBAction func segmentControl(_ sender: UISegmentedControl) {
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
cell.numberLbl.text = String(numberArray[indexPath.row])
if segmentOutlet.selectedSegmentIndex == 1 {
cell.numberLbl.text = String(numberArray[indexPath.row] % 2 == 0)
}
if segmentOutlet.selectedSegmentIndex == 2 {
cell.numberLbl.text = String(numberArray[indexPath.row] % 2 == 1)
}
return cell
}
}
my Simulator image:
Your numberArray[indexPath.row] % 2 == 0 has a ==, which evaluates to true/false. It doesn't really make sense. Also, there's no need to check if the current indexPath.row is odd or even... you're trying to display a list of even or odd numbers, so what does indexPath.row have to do with that?
Instead, try making a second array, filteredArray. This will be where the table view directly gets its data from.
let numberArray = Array(1...100)
lazy var filteredArray: [Int] = { numberArray }() /// return `numberArray` by default
You can then update filteredArray based on the selectedSegmentIndex.
#IBAction func segmentControl(_ sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 1: /// even numbers
filteredArray = numberArray.filter { $0 % 2 == 0}
case 2: /// odd numbers
filteredArray = numberArray.filter { $0 % 2 == 1}
default: /// all numbers
filteredArray = numberArray
}
tableView.reloadData()
}
Finally, just read from filteredArray in your data source methods.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredArray.count /// use `filteredArray`
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
cell.numberLbl.text = String(filteredArray[indexPath.row]) /// also use `filteredArray`
return cell
}

getting the wrong index when I search something on the searcher

This is an example to explain a problem that I’m having.
I have 3 elements in an array. the index of the array matches each sentences. Like
The 0 index matches “hello” (0 index)
The 1 index matches “nice” (1 index)
The 2 index matches “how are you?” (2 index)
I’ve put UISearchBar in my tableView. When I type “h” in the searchBar, “hello” and “how are you” show up perfectly, but the thing is, when I touch “how are you” which is 2 index on the tableview list, it shows “nice” on the next viewController (I have two viewControllers and the variable called myIndex use the index on the next viewController ) because the variable gets 1 index not 2 index. How should I solve this?
The full code is as follows :
import UIKit
class tableviewtest: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var searchBar: UISearchBar!
func tableView(_ tableView: UITableView,
moveRowAt sourceIndexPath: IndexPath,
to destinationIndexPath: IndexPath) {
}
var searchArr = [String]()
var searching = false
var copiedArray:[String] = eng // eng is the original array that has the full elements from another view controller.
let cellIdentifier = "xxx"
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableview.dequeueReusableCell(withIdentifier: cellIdentifier, for:indexPath)
if searching {
cell.textLabel?.text = searchArr[indexPath.row]
}
else {
cell.textLabel?.text = copiedArray[indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchArr.count
}
else {
return copiedArray.count
}
}
func tableView(_ tableview: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex = indexPath.row
performSegue(withIdentifier: "segue1", sender: self)
}
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableview.delegate = self
tableview.dataSource = self
self.tableview.register(UITableViewCell.self,forCellReuseIdentifier: cellIdentifier)
}
}
extension tableviewtest: UISearchBarDelegate {
func searchBar (_ searchBar:UISearchBar, textDidChange searchText: String) {
searchArr = copiedArray.filter({$0.prefix(searchText.count) == searchText})
searching = true
tableview.reloadData()
}
}
At the moment you get the string from the array you have to consider the searching state
let selectedItem = searching ? searchArr[myIndex] : filteredArr[myIndex]
and you have to reset searching if the search string is empty
func searchBar (_ searchBar:UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
searching = false
searchArr.removeAll()
} else {
searchArr = filteredArr.filter({$0.prefix(searchText.count) == searchText})
searching = true
}
tableview.reloadData()
}
You could even pass the string as sender parameter in performSegue and hand it over to the next view controller in prepare(for segue
func tableView(_ tableview: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedItem = searching ? searchArr[indexPath.row] : filteredArr[indexPath.row]
performSegue(withIdentifier: "segue1", sender: selectedItem)
}
Side note:
Reconsider your naming of the variables: Why is the data source array once called filteredArr and then numberOfRows, and why is the non-filtered array called filteredArr anyway?

Load more options with UITableView

Trying to load my data in page using pagination, I've already seen many examples but all are in Objective-C and some questions are unanswered.
My code:
class testTableViewController: UITableViewController {
//MARK: - Properties -
var allObjectArray: NSMutableArray = []
var elements: NSMutableArray = []
var currentPage = 0 //number of current page
var nextpage = 0
var selectedRow = Int()
//MARK: - View Life Cycle -
override func viewDidLoad() {
super.viewDidLoad()
for var i = 1; i < 500; i++ {
allObjectArray.addObject(i)
}
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(0, 30)))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source -
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return elements.count + 1
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = (tableView.indexPathForSelectedRow?.row)!
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var customCell = tableView.dequeueReusableCellWithIdentifier("cell")
customCell = UITableViewCell(style: .Default, reuseIdentifier: "cell")
customCell!.textLabel!.text = "cell - \(allObjectArray[indexPath.row])"
if indexPath.row == elements.count {
customCell?.textLabel?.textColor = UIColor.blueColor()
customCell?.textLabel?.text = "Load more..."
}
return customCell!
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
nextpage = elements.count
if indexPath.row == nextpage {
if indexPath.row == selectedRow {
currentPage++
nextpage = elements.count - 5
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(currentPage, 30)))
tableView.reloadData()
}
}
}
}
I want this kind of output:
Tried to fetch selected index but it will return nil.
Create Outlets in Interface Builder for tableview and make two dynamic prototype cells give them identifiers make one cell with a button(your load more cell button)
Then create action with that button that will contain the logic to load more cells!!!
now see the snipet below for reference...
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tblDemo: UITableView!
var arForCells:NSMutableArray = NSMutableArray()
let simpleCellID = "SimpleCell"
let loadMoreCell = "LoadMoreCell"
override func viewDidLoad() {
super.viewDidLoad()
tblDemo.delegate = self
tblDemo.dataSource = self
arForCells = NSMutableArray(objects: "1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arForCells.count + 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (indexPath.row == arForCells.count){
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(loadMoreCell, forIndexPath: indexPath)
return cell
}else {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(simpleCellID, forIndexPath: indexPath)
let lblCounter = cell.viewWithTag(111) as! UILabel
lblCounter.text = arForCells.objectAtIndex(indexPath.row) as! String
return cell
}
}
#IBAction func loadMoreCells(sender: AnyObject) {
let newAr:NSArray = NSArray(objects: "1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
arForCells.addObjectsFromArray(newAr as [AnyObject])
tblDemo.reloadData()
}}
as I have checked, It should give you the desired results.
You could also do the same in TableViewFooter.
To set "Load More.." text add a label with this text in a view having the same size of your tableViewCell. Then add this in your tableView footer. Add a (custom/transparent)button in footer view so when that touched it will load your main array with more data and then reload your tableView.
Hope this helps!
First of all, You don't have to use this:
selectedRow = (tableView.indexPathForSelectedRow?.row)!
in the didSelectRowAtIndexPath. You can use simply
selectedRow = indexPath.row
next, your logic for willDisplayCellAtIndexPath seems redundant if you want to have cell to tap on it. You can simply put the following in enter code here:
nextpage = elements.count
if indexPath.row == nextpage {
currentPage++
nextpage = elements.count - 5
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(currentPage, 30)))
tableView.reloadData()
}
also, I am not sure why do you need nextpage = elements.count - 5 but I assume that you have reason behind this.
done it my self
import UIKit
class LoadMoreTableVC: UITableViewController {
//MARK: - Properties -
var allObjectArray: NSMutableArray = []
var elements: NSMutableArray = []
var currentPage = 0 //number of current page
var nextpage = 0
var totalElements = 500 //total elements
var elementAtOnePage = 30 //at one page
//MARK: - View Life Cycle -
override func viewDidLoad() {
super.viewDidLoad()
for i in 0 ..< totalElements {
allObjectArray.addObject(i+1)
}
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(0, elementAtOnePage)))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source -
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let count = elements.count + 1
if count < allObjectArray.count
{
return count
}
else
{
return allObjectArray.count
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == elements.count {
loadDataDelayed()
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel!.text = "\(allObjectArray[indexPath.row])"
if indexPath.row == elements.count {
cell.textLabel?.text = "Load more..."
}
return cell
}
func loadDataDelayed(){
currentPage += 1
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(currentPage, elementAtOnePage)))
tableView.reloadData()
}
}
I have already done this is in swift.
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
if loading == true {
var endScrolling:CGFloat = scrollView.contentOffset.y + scrollView.frame.size.height
if(endScrolling >= scrollView.contentSize.height){
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "loadDataDelayed", userInfo: nil, repeats: false)
}
}
}
Please try this code.
And share your response.
Happy coding :)

Setting rowHeight equal to UITableViewAutomaticDimension not working

I'm using XCode 6.3 to build a TableView of the different Fonts in iOS 8. First, per the book I'm reading, it said that nothing needed to be done regarding the height of the table rows, given that iOS8 takes care of that for you, so once I had everything per the book, the rows should update their heights based on their content, which wasn't the case. Then I tried to play with tableView.rowHeight and I set it equal to UITableViewAutomaticDimension in the TableViewController's viewDidLoad function, and that didn't work either. I also tried changing the height of the rows from Interface Builder, and that didn't seem to have any effect on the heights either. My code is as follows:
class RootViewController: UITableViewController {
private var familyNames: [String]!
private var cellPointSize: CGFloat!
private var favoritesList: FavoritesList!
private let familyCell = "FamilyName"
private let favoritesCell = "Favorites"
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = UITableViewAutomaticDimension
familyNames = sorted(UIFont.familyNames() as! [String])
let preferredTableViewFont = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cellPointSize = preferredTableViewFont.pointSize
favoritesList = FavoritesList.sharedFavoritesList
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
func fontForDisplay(atIndexPath indexPath: NSIndexPath) -> UIFont? {
if indexPath.section == 0 {
let familyName = familyNames[indexPath.row]
let fontName = UIFont.fontNamesForFamilyName(familyName).first as! String
return UIFont(name: fontName, size: cellPointSize)
} else {
return nil
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return favoritesList.favorites.isEmpty ? 1 : 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return section == 0 ? familyNames.count : 1
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return section == 0 ? "All Font Families" : "Favorite Fonts"
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier(familyCell, forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.font = fontForDisplay(atIndexPath: indexPath)
cell.textLabel!.text = familyNames[indexPath.row]
cell.detailTextLabel!.text = familyNames[indexPath.row]
return cell
} else {
return tableView.dequeueReusableCellWithIdentifier(favoritesCell, forIndexPath: indexPath) as! UITableViewCell
}
}
}
When I run this in the simulator, everything looks right until I scroll all the way to the bottom and I get this:
The attributes of the FontFamily cell are: style = subtitle, and accessory = disclosure indicator.
Any ideas on what I'm be doing wrong?
You must set self.tableView.estimatedRowHeight

UITableView going out of view

i have a UITableView with multiple selection enabled with checkmarks. When i make selection that are all visible in the view, i don't run into any errors. However, if i scroll down further and place a selected item out of view, i get errors and even though the row stays selected, the checkmark goes away.
import Foundation
import Parse
import UIKit
class customerMenuVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var menuTV: UITableView!
var menuItems: [String] = ["Hello"]
var menuPrices: [Double] = [0.0]
var orderSelection: [String] = []
var priceSelection: [Double] = []
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return menuItems.count
}
func tableView(tableView: UITableView, numberOfColumnsInSection section: Int) -> Int
{
return 1;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "mycell")
cell.textLabel!.text = "\(menuItems[indexPath.row])\t $\(menuPrices[indexPath.row])"
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
//tableView.deselectRowAtIndexPath(indexPath, animated: true)
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.accessoryType = .Checkmark
orderSelection.append(cell!.textLabel!.text!)
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
{
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.accessoryType = .None
}
override func viewDidLoad() {
super.viewDidLoad()
menuTV.allowsMultipleSelection = true
let resMenu = resUser.sharedInstance
var resName = resMenu.nameStr
var resID = resMenu.idStr
var menuQ = PFQuery(className: "menu")
menuQ.getObjectInBackgroundWithId(resID){
(menus: PFObject?, error: NSError?) -> Void in
if error == nil && menus != nil {
let items: [String] = menus?.objectForKey("menuItems") as! Array
let prices: [Double] = menus?.objectForKey("menuPrices") as! Array
self.menuItems = items
self.menuPrices = prices
self.menuTV.reloadData()
}
}
}
#IBAction func continueButton(sender: AnyObject) {
let selections = menuTV.indexPathsForSelectedRows() as! [NSIndexPath]
var indexCount = selections.count
println(indexCount)
var x = 0
while x < indexCount
{
println(x)
let currentCell = menuTV.cellForRowAtIndexPath(selections[x]) as? UITableViewCell?;
println(x)
println(selections[x].row.description)
orderSelection.append(currentCell!!.textLabel!.text!)
println(orderSelection[x])
x++
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
This is how table views work.
When a cells scrolls off-screen, it gets tossed into the recycle queue and then used again to display data for a different indexPath in your data.
Any time the user makes any changes to the data for a cell you should save it to your data model (usually an array of information, or maybe an array of arrays if you're using a sectioned table view.) Then you should tell the table view to redisplay the changed cell. The cellForRowAtIndexPath method picks up the changed data and shows the changes to the cell. If the cell scrolls off-screen and then scrolls back on-screen, it gets displayed with the correct settings.
This applies to keeping track of which cells are selected as well.

Resources