3

I am trying to control my UITableView based on the selectedSegmentIndex of a UISegmentedControl inside my UITableView header. Essentially, I want this UISegmentedControl to work like Twitter's 'Me' tab. I have the UISegmentedControl inside a UITableView header and it is dequeued using this method:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let cell = tableView.dequeueReusableCell(withIdentifier: "sectionDetailsHeaderView") as! SectionDetailsHeaderTableViewCell
    return cell
}

I have an outlet for the UISegmentedControl hooked up to SectionDetailsHeaderTableViewCell, but I can't figure out how to detect a change in the UISegmentedControl. I want to set a variable, var segmentedControlValue = Int() to the selectedSegmentIndex every time the value changes and call a function, func chooseDataToDisplay() {} when the value changes. How do I go about doing this?

Dan Levy
  • 3,931
  • 4
  • 28
  • 48
  • without seeing more of your code, maybe your model has already detected the segment selected, but the view end of MVC needs updating accordingly. I'm wrestling with this very thing now. – aremvee Jan 07 '17 at 03:08
  • Check out my answer below! – Dan Levy Jan 08 '17 at 13:30

2 Answers2

5

With the help of @Schomes answer and this post, I was able to figure it out!

1) Add the UISegmentedControl into its own UITableViewCell. I would recommend adding a UIView with a white background behind the UISegmentedControl that covers the entire UITableViewCell so the TableView cells flow behind the UISegmentedControl.

2) Add your custom cell class and hook it up to the UITableViewCell

3) Add an outlet, such as yourSegmentedControl to your custom UITableViewCell class. DO NOT add an action into the custom UITableViewCell class. This is done programmatically in step 4.

4) In the UIViewController or UITableViewController class, add the code below.

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "yourCellIdentifier") as! yourCustomCellClass
    header.yourSegmentedControl.selectedSegmentIndex = self.segmentedControlValue
    header.yourSegmentedControl.addTarget(self, action: #selector(self.getSegmentValue(sender:)), for: .valueChanged)
    return header
}

self.segmentedControlValue should be declared as var segmentedControlValue = Int() at the top of your ViewController class. self.getSegmentValue(sender:) should be declared as:

func getSegmentValue(sender: UISegmentedControl) {
    self.segmentedControlValue = sender.selectedSegmentIndex
}

5) You also need to add:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 45
}

This is the height of the header. In my case, the size is 45

6) You can now access self.segmentedControlValue anywhere in your ViewController. It will update when the user taps on a different segment.

Dan Levy
  • 3,931
  • 4
  • 28
  • 48
  • Finally .. I had declared action in cell class and were using delegate to achieve the result, it was working but it has a flaws, then your answer made my night.. Thanks.. – Abhishek Mitra Mar 12 '18 at 21:02
  • @AbhishekMitra Glad this helped! I just updated my answer to use dequeueReusableHeaderFooterView instead of dequeueReusableCell. Calling dequeueReusableCell can cause problems when reloading the UITableView – Dan Levy Mar 12 '18 at 21:09
  • Yes, everything I used before seen your answer, only i had missed this line `header.yourSegmentedControl.selectedSegmentIndex = self.segmentedControlValue` in my code, and finally your answer helped to get over it. Thanks once again. I up voted your question and answers.. :) – Abhishek Mitra Mar 12 '18 at 21:14
1
segmentedControl.addTarget(self, action: "chooseDataToDisplay:", forControlEvents: .ValueChanged)

Where segmentedControl is your UISegmentedControl. This will call func chooseDataToDisplay(segment: UISegmentedControl) {} every time the value changes.

References:

https://developer.apple.com/reference/uikit/uisegmentedcontrol

The section Behavior of Segmented Controls https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/UIKitUICatalog/UISegmentedControl.html#//apple_ref/doc/uid/TP40012857-UISegmentedControl

Schomes
  • 156
  • 6
  • This doesn't seem to work. The selected segment never gets highlighted and the value never changes. I looked at: http://stackoverflow.com/questions/30545198/swift-handle-action-on-segmented-control but it didn't help either. – Dan Levy Jan 07 '17 at 03:39
  • 1
    Maybe look at these answers http://stackoverflow.com/questions/18588941/uisegmentedcontrol-not-updating-view http://stackoverflow.com/questions/2718956/problem-in-inserting-segmented-control-to-header-view – Schomes Jan 07 '17 at 03:46
  • Awesome! This answer and one of the answers in your comment helped! I will post the answer that worked for me. – Dan Levy Jan 07 '17 at 03:58