Uisegment Value Changing When Tableview Get Scrolled

UISegment value changing when tableview get scrolled

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

UITableView: reloadRows(at:) takes two hits for table to be updated and scroll every time

Your UISegmentedControl are reusing [Default behaviour of UITableView].

To avoid that, keep dictionary for getting and storing values.

Another thing, try outlet connection as Action for UISegmentedControl in UIViewController itself, instead of your UITableViewCell

The below code will not reload your tableview when you tap UISegmentedControl . You can avoid, delegates call too.

Below codes are basic demo for UISegmentedControl. Do customise as per your need.

var segmentDict = [Int : Int]()

override func viewDidLoad() {
super.viewDidLoad()

for i in 0...29 // number of rows count
{
segmentDict[i] = 0 //DEFAULT SELECTED SEGMENTS
}

}

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

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

cell.mySegment.selectedSegmentIndex = segmentDict[indexPath.row]!

cell.selectionStyle = .none
return cell
}

@IBAction func mySegmentAcn(_ sender: UISegmentedControl) {

let cellPosition = sender.convert(CGPoint.zero, to: tblVw)
let indPath = tblVw.indexPathForRow(at: cellPosition)

segmentDict[(indPath?.row)!] = sender.selectedSegmentIndex

print("Sender.tag ", indPath)

}

Why is scrolling performance poor for custom table view cells having UISegmentedControl objects?

Any drawing that a table cell has to do while it's being scrolled is going to cause performance issues; when you have a lot of subviews, there tends to be a lot of drawing going on, and that will—as you've observed—make your scrolling pretty choppy. There are a couple of ways to try to reduce that.

The first step is to make sure that your cells themselves, and as many of their subviews as possible, have their opaque properties set to YES. Opaque views don't have to get blended with the content underneath them, and that saves a lot of time.

You may also want to set your cells' layers to rasterize themselves, like this:

cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

This will collapse your view hierarchy into one flat bitmap, which is the kind of thing Core Animation just loves to draw. Note that any animating views—activity indicators, for instance—will force that bitmap to be updated every time they change, i.e. a lot. In that case, you won't want the cell to rasterize everything; you might just use a subview with all of your relatively static views (e.g. labels) beneath another subview with any such dynamic content, and only have the first of those rasterized.

How do I keep the selected segment of UISegmentedControl inside UITableView when cell is reused?

Your model for each row should have a property that keeps the selected segment, lets call it selectedSegment. When the user clicks on a segment you affect the value of the selectedSegment property for the instance of the object representing the affected row.

Then in your cellForRowAtIndexPath: method, you update the UISegmentedControl's selected index with the value of the selectedSegment property.



Related Topics



Leave a reply



Submit