UISegment value changing when tableview get scrolled

可紊 提交于 2019-12-19 11:55:28

问题


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:


回答1:


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)")
}



回答2:


You're having this problem because of how dequeueReusableCellWithIdentifier: works. Each time a cell get scrolled out of screen, it enters a cache area where it will be reused.

Let's say you have 100 cells. All their segmentedControl objects are set to first. You tap on one to change it's value. As the cell moves out of view, it enters the cache, where it will be dequeued if you scroll down further.

It's important to understand this, because the segmentedControl object is not actually changing. It looks like it's changing because of the dequeue behaviour.

To solve this problem, you will need to implement a dataSource that stores the segmentedControl object's value so you can reinitialize it correctly every time a cell is dequeued.




回答3:


@KelvinLau's is perfect

you can do that by using var segmentedTracker : [NSIndexPath:Int] = [:]

on segmentedValueChanged set the value of the selectedIndex ie: segmentedTracker[indexPath] = valueOf the selected index

then in cellForRowAtIndexPath check for the value let selected = [segmentedTracker]

cell.yourSegmentedControlReference.selectedIndex = selected

please note this is a pseudocode I don't remember the properties name. From here you can figure it out by urself




回答4:


I think to use UISegmentControl in UITableViewCell may be wrong.

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UISegmentedControl_Class/

I have never seen the kind of that in iOS application.

The problem is that UITableViewCell is reused by dequeueReusableCellWithIdentifier method. So some UISegmentControl values are changed when scrolling.

Although it is not best solution, you can use Static Cells. What you need to do is that only switch Static cells. And If so, you don't write code of UITableViewCell.




回答5:


Year 2018: Updated Answer

Find my easiest answer in this UISegement inside UITableViewCell

=======================================================

Year 2015

I have tested in my own way. My coding is below. Kindly guide me, whether it is right way or wrong way? My problem get solved. This code stops reusable cell.

My Coding Below:

//UIViewController
var globalCell = segmentTblCell()  //CUSTOM UITableViewCell Class

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

    globalCell  = segTblVw.dequeueReusableCellWithIdentifier("segment", forIndexPath: indexPath) as! segmentTblCell  //THIS LINE - STOPS REUSABLE TABLE.

    return cell
}


来源:https://stackoverflow.com/questions/32351998/uisegment-value-changing-when-tableview-get-scrolled

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!