UISegmentedControl
iOS Development
Swift
User Interface
Mobile App Development

get string value from UISegmentedControl

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

UISegmentedControl provides the selected segment's index via its selectedSegmentIndex property, not the title string directly. To get the string value, call titleForSegment(at:) with the selected index. This returns an Optional<String> because the segment might use an image instead of a title, or the index could be UISegmentedControl.noSegment (-1) when nothing is selected.

Getting the Selected Segment Title

swift
1let segmentedControl = UISegmentedControl(items: ["Daily", "Weekly", "Monthly"])
2segmentedControl.selectedSegmentIndex = 0
3
4// Get the selected title
5let selectedIndex = segmentedControl.selectedSegmentIndex
6let selectedTitle = segmentedControl.titleForSegment(at: selectedIndex)
7
8print(selectedTitle)  // Optional("Daily")

Always unwrap safely since the result is optional:

swift
1if let title = segmentedControl.titleForSegment(at: segmentedControl.selectedSegmentIndex) {
2    print("Selected: \(title)")
3} else {
4    print("No segment selected or segment has no title")
5}

Responding to Selection Changes

Use a target-action or @IBAction to respond when the user taps a segment:

swift
1// Programmatic setup
2segmentedControl.addTarget(self, action: #selector(segmentChanged(_:)), for: .valueChanged)
3
4@objc func segmentChanged(_ sender: UISegmentedControl) {
5    let index = sender.selectedSegmentIndex
6    if let title = sender.titleForSegment(at: index) {
7        print("Selected: \(title)")
8        updateUI(for: title)
9    }
10}

With Interface Builder:

swift
1@IBAction func segmentChanged(_ sender: UISegmentedControl) {
2    guard let title = sender.titleForSegment(at: sender.selectedSegmentIndex) else { return }
3    filterLabel.text = "Filter: \(title)"
4}

Mapping Segments to Enum Values

For type-safe handling, map segment indices to an enum:

swift
1enum TimePeriod: Int, CaseIterable {
2    case daily = 0
3    case weekly = 1
4    case monthly = 2
5
6    var displayName: String {
7        switch self {
8        case .daily: return "Daily"
9        case .weekly: return "Weekly"
10        case .monthly: return "Monthly"
11        }
12    }
13}
14
15// Create segmented control from enum
16let items = TimePeriod.allCases.map { $0.displayName }
17let segmentedControl = UISegmentedControl(items: items)
18
19// Get the enum value on selection
20@objc func segmentChanged(_ sender: UISegmentedControl) {
21    guard let period = TimePeriod(rawValue: sender.selectedSegmentIndex) else { return }
22
23    switch period {
24    case .daily:
25        loadDailyData()
26    case .weekly:
27        loadWeeklyData()
28    case .monthly:
29        loadMonthlyData()
30    }
31}

Getting All Segment Titles

swift
1func getAllTitles(from control: UISegmentedControl) -> [String] {
2    return (0..<control.numberOfSegments).compactMap { index in
3        control.titleForSegment(at: index)
4    }
5}
6
7let titles = getAllTitles(from: segmentedControl)
8print(titles)  // ["Daily", "Weekly", "Monthly"]

Setting and Modifying Segment Titles

swift
1let control = UISegmentedControl(items: ["One", "Two", "Three"])
2
3// Change a segment title
4control.setTitle("First", forSegmentAt: 0)
5
6// Insert a new segment
7control.insertSegment(withTitle: "Four", at: 3, animated: true)
8
9// Remove a segment
10control.removeSegment(at: 1, animated: true)
11
12// Replace all segments
13control.removeAllSegments()
14for (index, title) in ["A", "B", "C"].enumerated() {
15    control.insertSegment(withTitle: title, at: index, animated: false)
16}

Handling No Selection

swift
1let control = UISegmentedControl(items: ["Option A", "Option B"])
2// No segment selected initially if isMomentary = true or selectedSegmentIndex not set
3
4if control.selectedSegmentIndex == UISegmentedControl.noSegment {
5    print("Nothing selected")
6} else if let title = control.titleForSegment(at: control.selectedSegmentIndex) {
7    print("Selected: \(title)")
8}

UISegmentedControl.noSegment equals -1. Passing -1 to titleForSegment(at:) returns nil.

SwiftUI Equivalent

In SwiftUI, use Picker with SegmentedPickerStyle:

swift
1struct ContentView: View {
2    @State private var selection = "Daily"
3    let options = ["Daily", "Weekly", "Monthly"]
4
5    var body: some View {
6        Picker("Period", selection: $selection) {
7            ForEach(options, id: \.self) { option in
8                Text(option).tag(option)
9            }
10        }
11        .pickerStyle(.segmented)
12
13        Text("Selected: \(selection)")  // Directly a String, no unwrapping needed
14    }
15}

SwiftUI binds the selected value directly to a String variable — no index-to-title conversion needed.

Common Pitfalls

  • Not handling noSegment (-1): If no segment is selected, selectedSegmentIndex returns -1. Passing this to titleForSegment(at:) returns nil. Always check for UISegmentedControl.noSegment before accessing the title.
  • Force-unwrapping the optional title: titleForSegment(at:) returns String?. Segments can use images instead of titles, so nil is a valid return. Force-unwrapping (title!) crashes if the segment has an image instead of a title.
  • Using hard-coded index-to-string mapping: if index == 0 { return "Daily" } breaks when segments are reordered or titles change. Use titleForSegment(at:) or an enum mapped to indices for maintainable code.
  • Forgetting to set an initial selection: If selectedSegmentIndex is not set, it defaults to -1 (no selection) unless set in Interface Builder. Users see no highlighted segment, and reading the title returns nil.
  • Not connecting the valueChanged event: UISegmentedControl fires .valueChanged when the user taps a different segment. If you connect to .touchUpInside instead, the action never fires.

Summary

  • Use titleForSegment(at: selectedSegmentIndex) to get the selected segment's string value
  • The return type is String? — always unwrap safely with if let or guard let
  • Connect to the .valueChanged control event to respond to segment changes
  • Map indices to an enum for type-safe segment handling
  • selectedSegmentIndex returns -1 (noSegment) when nothing is selected
  • In SwiftUI, use Picker with .segmented style for direct string binding

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.