Bird
Raised Fist0
iOS Swiftmobile~20 mins

Picker and DatePicker in iOS Swift - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Picker and DatePicker Screen
This screen lets the user pick a fruit from a list and select a date using a date picker. The selected fruit and date are shown below the pickers.
Target UI
-------------------------
| Picker and DatePicker |
-------------------------
| Fruit:                |
| [Picker wheel here]   |
|                       |
| Date:                 |
| [Date picker here]    |
|                       |
| Selected Fruit:       |
| [Shows chosen fruit]  |
| Selected Date:        |
| [Shows chosen date]   |
-------------------------
Add a UIPickerView to select a fruit from a list of at least 5 fruits.
Add a UIDatePicker to select a date.
Show the selected fruit below the picker in a UILabel.
Show the selected date below the date picker in a UILabel formatted as MM/dd/yyyy.
Update the labels immediately when the user changes the picker or date.
Starter Code
iOS Swift
import UIKit

class PickerDatePickerViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    let fruits = ["Apple", "Banana", "Cherry", "Date", "Grape"]

    // TODO: Add UIPickerView, UIDatePicker, and UILabels as properties

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        // TODO: Initialize and add UIPickerView
        // TODO: Initialize and add UIDatePicker
        // TODO: Initialize and add UILabels for selected fruit and date

        // TODO: Set delegates and targets
    }

    // TODO: Implement UIPickerViewDataSource methods

    // TODO: Implement UIPickerViewDelegate methods

    // TODO: Add method to handle date picker value change
}
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Task 7
Solution
iOS Swift
import UIKit

class PickerDatePickerViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    let fruits = ["Apple", "Banana", "Cherry", "Date", "Grape"]

    let pickerView = UIPickerView()
    let datePicker = UIDatePicker()
    let selectedFruitLabel = UILabel()
    let selectedDateLabel = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        // Setup pickerView
        pickerView.delegate = self
        pickerView.dataSource = self
        pickerView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(pickerView)

        // Setup datePicker
        datePicker.datePickerMode = .date
        datePicker.preferredDatePickerStyle = .wheels
        datePicker.translatesAutoresizingMaskIntoConstraints = false
        datePicker.addTarget(self, action: #selector(dateChanged), for: .valueChanged)
        view.addSubview(datePicker)

        // Setup selectedFruitLabel
        selectedFruitLabel.text = "Selected Fruit: Apple"
        selectedFruitLabel.textAlignment = .center
        selectedFruitLabel.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(selectedFruitLabel)

        // Setup selectedDateLabel
        selectedDateLabel.textAlignment = .center
        selectedDateLabel.translatesAutoresizingMaskIntoConstraints = false
        updateDateLabel(date: datePicker.date)
        view.addSubview(selectedDateLabel)

        // Layout constraints
        NSLayoutConstraint.activate([
            pickerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            pickerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            pickerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            pickerView.heightAnchor.constraint(equalToConstant: 150),

            datePicker.topAnchor.constraint(equalTo: pickerView.bottomAnchor, constant: 20),
            datePicker.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            datePicker.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            datePicker.heightAnchor.constraint(equalToConstant: 150),

            selectedFruitLabel.topAnchor.constraint(equalTo: datePicker.bottomAnchor, constant: 20),
            selectedFruitLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            selectedFruitLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            selectedFruitLabel.heightAnchor.constraint(equalToConstant: 30),

            selectedDateLabel.topAnchor.constraint(equalTo: selectedFruitLabel.bottomAnchor, constant: 10),
            selectedDateLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            selectedDateLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
            selectedDateLabel.heightAnchor.constraint(equalToConstant: 30)
        ])
    }

    // MARK: - UIPickerViewDataSource
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return fruits.count
    }

    // MARK: - UIPickerViewDelegate
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return fruits[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        selectedFruitLabel.text = "Selected Fruit: \(fruits[row])"
    }

    // MARK: - DatePicker action
    @objc func dateChanged() {
        updateDateLabel(date: datePicker.date)
    }

    func updateDateLabel(date: Date) {
        let formatter = DateFormatter()
        formatter.dateFormat = "MM/dd/yyyy"
        selectedDateLabel.text = "Selected Date: \(formatter.string(from: date))"
    }
}

We created a UIViewController subclass that implements UIPickerViewDelegate and UIPickerViewDataSource to manage the fruit picker. We added a UIPickerView and a UIDatePicker to the view, along with two UILabels to show the selected fruit and date.

The picker view shows a single column with the fruit names. When the user selects a fruit, the label updates immediately.

The date picker uses the wheel style and triggers an action when the date changes. The selected date is formatted as MM/dd/yyyy and shown in the label below.

All UI elements use Auto Layout constraints for proper positioning and responsiveness.

Final Result
Completed Screen
-------------------------
| Picker and DatePicker |
-------------------------
| Fruit:                |
| [Apple]               |
|                       |
| Date:                 |
| [06/15/2024]          |
|                       |
| Selected Fruit: Apple  |
| Selected Date: 06/15/2024 |
-------------------------
User scrolls the picker wheel to select a different fruit; the Selected Fruit label updates immediately.
User scrolls the date picker wheel to change the date; the Selected Date label updates immediately.
Stretch Goal
Add a button that resets the picker and date picker to their default values (first fruit and today's date).
💡 Hint
Add a UIButton below the labels. When tapped, set pickerView.selectRow(0, inComponent: 0, animated: true) and datePicker.date = Date(), then update labels.

Practice

(1/5)
1. What is the primary purpose of a Picker in SwiftUI?
easy
A. To input text from the keyboard
B. To display a calendar view for date selection
C. To let users select a value from a list of options
D. To show an alert message

Solution

  1. Step 1: Understand Picker functionality

    A Picker is designed to let users choose from multiple options easily.
  2. Step 2: Compare with other UI elements

    DatePicker is for dates, TextField is for text input, Alert is for messages.
  3. Final Answer:

    To let users select a value from a list of options -> Option C
  4. Quick Check:

    Picker = select from list [OK]
Hint: Picker = choose from list, DatePicker = choose date [OK]
Common Mistakes:
  • Confusing Picker with DatePicker
  • Thinking Picker inputs text
  • Assuming Picker shows alerts
2. Which of the following is the correct syntax to create a simple Picker in SwiftUI?
easy
A. Picker { Text("One") } selection: $choice label: Text("Select")
B. Picker(selection: $choice) { Text("One") } label: { Text("Select") }
C. Picker(label: Text("Select"), selection: $choice) { Text("One") }
D. Picker(selection: choice) { Text("One") } label: Text("Select")

Solution

  1. Step 1: Recall Picker initializer syntax

    The correct syntax uses named parameters: selection binding first, then content closure, then label closure.
  2. Step 2: Check each option

    Picker(selection: $choice) { Text("One") } label: { Text("Select") } matches the correct syntax with $choice binding and label closure.
  3. Final Answer:

    Picker(selection: $choice) { Text("One") } label: { Text("Select") } -> Option B
  4. Quick Check:

    Picker syntax = selection: $var, content, label [OK]
Hint: Picker needs selection binding with $ and label closure [OK]
Common Mistakes:
  • Omitting $ for binding
  • Wrong parameter order
  • Using non-closure label
3. Given this SwiftUI code snippet, what will be displayed when the user selects "Banana"?
struct ContentView: View {
  @State private var fruit = "Apple"
  var fruits = ["Apple", "Banana", "Cherry"]

  var body: some View {
    VStack {
      Picker("Select Fruit", selection: $fruit) {
        ForEach(fruits, id: \.self) { fruit in
          Text(fruit)
        }
      }
      Text("You chose: \(fruit)")
    }
  }
}
medium
A. You chose: Banana
B. You chose: "" (empty string)
C. You chose: Cherry
D. You chose: Apple

Solution

  1. Step 1: Understand state binding in Picker

    The Picker binds to @State variable 'fruit', updating it when user selects an option.
  2. Step 2: User selects "Banana"

    The state variable 'fruit' changes to "Banana", so the Text below shows "You chose: Banana".
  3. Final Answer:

    You chose: Banana -> Option A
  4. Quick Check:

    Picker selection updates state = displayed text [OK]
Hint: Picker updates bound state, Text shows updated value [OK]
Common Mistakes:
  • Ignoring state update on selection
  • Confusing initial value with selected value
  • Not using id: \.self in ForEach
4. Identify the error in this DatePicker code snippet:
@State private var selectedDate = Date()

var body: some View {
  DatePicker("Pick a date", selection: selectedDate, displayedComponents: .date)
}
medium
A. DatePicker cannot display only date component
B. selectedDate must be a String, not Date
C. Label parameter must be omitted
D. Missing $ before selectedDate in selection binding

Solution

  1. Step 1: Check binding syntax for DatePicker

    The selection parameter requires a binding, so it must be $selectedDate, not selectedDate.
  2. Step 2: Verify other parameters

    Displaying only date is valid, label is required, and selectedDate is correctly a Date type.
  3. Final Answer:

    Missing $ before selectedDate in selection binding -> Option D
  4. Quick Check:

    Binding needs $ prefix [OK]
Hint: Always use $ for binding state variables [OK]
Common Mistakes:
  • Forgetting $ in binding
  • Using wrong data type for selection
  • Misunderstanding displayedComponents usage
5. You want to create a SwiftUI view where users pick a time and a fruit from a list. Which code snippet correctly combines a DatePicker for time and a Picker for fruits with state variables?
hard
A. struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker(selection: $time, displayedComponents: .hourAndMinute) { Text("Select Time") } Picker(selection: $fruit) { ForEach(fruits, id: \.self) { Text($0) } } label: { Text("Select Fruit") } } } }
B. struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker("Select Time", selection: time, displayedComponents: .hourAndMinute) Picker("Select Fruit", selection: fruit) { ForEach(fruits, id: \.self) { Text($0) } } } } }
C. struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker("Select Time", selection: time, displayedComponents: .hourAndMinute) Picker("Select Fruit", selection: $fruit) { ForEach(fruits, id: \.self) { Text($0) } } } } }
D. struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker("Select Time", selection: $time) Picker("Select Fruit", selection: $fruit) { ForEach(fruits, id: \.self) { Text($0) } } } } }

Solution

  1. Step 1: Check DatePicker syntax with label closure

    struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker(selection: $time, displayedComponents: .hourAndMinute) { Text("Select Time") } Picker(selection: $fruit) { ForEach(fruits, id: \.self) { Text($0) } } label: { Text("Select Fruit") } } } } uses DatePicker with selection binding and label closure, which is valid syntax.
  2. Step 2: Check Picker syntax with label closure

    Picker in struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker(selection: $time, displayedComponents: .hourAndMinute) { Text("Select Time") } Picker(selection: $fruit) { ForEach(fruits, id: \.self) { Text($0) } } label: { Text("Select Fruit") } } } } uses selection binding and label closure correctly, with ForEach and id: \.self.
  3. Step 3: Verify other options

    struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker("Select Time", selection: time, displayedComponents: .hourAndMinute) Picker("Select Fruit", selection: $fruit) { ForEach(fruits, id: \.self) { Text($0) } } } } } lacks $ for DatePicker selection binding, struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker("Select Time", selection: time, displayedComponents: .hourAndMinute) Picker("Select Fruit", selection: fruit) { ForEach(fruits, id: \.self) { Text($0) } } } } } lacks $ for bindings, struct ContentView: View { @State private var time = Date() @State private var fruit = "Apple" let fruits = ["Apple", "Banana"] var body: some View { VStack { DatePicker("Select Time", selection: $time) Picker("Select Fruit", selection: $fruit) { ForEach(fruits, id: \.self) { Text($0) } } } } } misses displayedComponents for time.
  4. Final Answer:

    The code using selection-first initializers with label closures -> Option A
  5. Quick Check:

    Use bindings with $ and label closures for both controls [OK]
Hint: Use $ for bindings and label closures for Picker and DatePicker [OK]
Common Mistakes:
  • Omitting $ in bindings
  • Missing label closures
  • Not specifying displayedComponents for time
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard