Detect Change in UISegmentedControl inside UITableView HeaderView

1.8k views Asked by At

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?

2

There are 2 answers

3
Dan Levy On BEST ANSWER

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.

3
Schomes On
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