Search code examples
swiftuitableviewuisegmentedcontrol

UISegment value changing when tableview get scrolled


I am using UISegmentControl to display objective type questions in table view. But, if I select one segment in any one of cell, then if I scroll, some segment values are changed. I dont know how to solve that. Kindly guide me.

Cell size : 160px

Segment tint color : blue color

Coding

//UIViewController
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = segTblVw.dequeueReusableCellWithIdentifier("segment", forIndexPath: indexPath) as! segmentTblCell

        return cell
    }

//UITableViewCell CLASS
class segmentTblCell: UITableViewCell {



    @IBOutlet weak var segMent: UISegmentedControl!


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

Screen shot below:

enter image description here


Solution

  • Method 1: Prevent reusability of cells by, Holding all cell objects in an array

    var arraysCells : NSMutableArray = []//globally declare this
    

    in viewDidLoad()

    for num in yourQuestionArray//this loop is to create all cells at beginning 
    {
         var nib:Array = NSBundle.mainBundle().loadNibNamed("SegmentTableViewCell", owner: self, options: nil)
         var cell = nib[0] as? SegmentTableViewCell
         arraysCells.addObject(cell!);
    }
    

    in tableViewDelegate,

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        return arraysCells.objectAtIndex(indexPath.row) as! UITableViewCell
    }
    

    you can find the selected segment values (answer) by iterating arraysCells

    NOTE: Method 1 will be slow, if you have big number of cells

    Method 2: Reuse the cell as normal, but save the states(enterd values) Using Delegate and arrays.

    in custom UITableViewCell

    @objc protocol SegmentTableViewCellDelegate {
    func controller(controller: SegmentTableViewCell, selectedSegmentIndex:Int, indexPath : NSIndexPath)
    }
    
    class SegmentTableViewCell: UITableViewCell {
    
    var delegate: AnyObject?
    var indexPath : NSIndexPath?
    
    @IBOutlet weak var segment: UISegmentedControl! //outlet of segmented Control
    
    @IBAction func onSegmentValueChanged(sender: UISegmentedControl/*if the parameter type is AnyObject changed it as  UISegmentedControl*/)//action for Segment
    {
        self.delegate?.controller(self, selectedSegmentIndex: sender.selectedSegmentIndex, indexPath: indexPath!)
    }
    

    in viewController

    class MasterViewController: SegmentTableViewCellDelegate{
    var selectedAnswerIndex : NSMutableArray = []  //globally declare this
    var selectedSegmentsIndexPath : NSMutableArray = [] //globally declare this
    
    
    func controller(controller: SegmentTableViewCell, selectedSegmentIndex:Int, indexPath : NSIndexPath)
    {
        if(selectedSegmentsIndexPath.containsObject(indexPath))
        {
            selectedAnswerIndex.removeObjectAtIndex(selectedSegmentsIndexPath.indexOfObject(indexPath))
            selectedSegmentsIndexPath.removeObject(indexPath)
        }
        selectedAnswerIndex.addObject(selectedSegmentIndex)
        selectedSegmentsIndexPath.addObject(indexPath)
    }
    

    in cellForRowAtIndexPath (tableView Delegate)

    if(selectedSegmentsIndexPath.containsObject(indexPath))
    {
     cell?.segment.selectedSegmentIndex = selectedAnswerIndex.objectAtIndex(selectedSegmentsIndexPath.indexOfObject(indexPath)) as! Int
    }
    cell?.delegate = self
    cell?.indexPath = indexPath
    

    you can get the result by

    for index in selectedSegmentsIndexPath
    {
      var  cellIndexPath = index as! NSIndexPath
      var answer : Int = selectedAnswerIndex.objectAtIndex(selectedSegmentsIndexPath.indexOfObject(cellIndexPath)) as! Int
      NSLog("You have enterd answer \(answer) for question number \(cellIndexPath.row)")
    }