SwiftUI

DatePicker & Picker 사용하기

GREEN.1229 2023. 9. 11. 09:52

안녕하세요. 그린입니다 🍏

이번 포스팅에서는 SwiftUI로 DatePicker와 Picker 컴포넌트를 사용하는 방법에 대해 학습해보겠습니다 🙌

 

두 컴포넌트 모두 이름에서 알 수 있듯이 어떠한걸 선택하는 용도로 사용되는 컴포넌트겠죠!?

사실 되게 간단한 컴포넌트들이고 사용하기 나름이기에 한번 기본적인 사용법을 익혀볼께요!

 

그럼 DatePicker부터 바로 가보겠습니다 😁


DatePicker

A control for selecting an absolute date

DatePicker는 이름에서도 바로 알 수 있듯이 어떤 날짜를 선택해주는 역할을 지닌 컴포넌트입니다.

즉, 쉽게 말해 사용자가 특정 날짜를 선택할 수 있도록 하는 사용자 인터페이스 컴포넌트를 의미하죠.

날짜/시간을 선택할 수 있습니다!

 

struct DatePicker<Label> where Label : View

 

선언은 이렇게 타이틀을 나타낼 수 있는 레이블을 제네릭하게 받는 구조입니다.

 

그럼 예시 코드로 한번 구현해볼까요?

 

struct ContentView: View {
  @State private var date = Date()
  
  var body: some View {
    DatePicker(
      "Select Date",
      selection: $date,
      displayedComponents: [.date, .hourAndMinute]
    )
    .padding(.horizontal, 20)
  }
}

 

이렇게 예시 코드가 주어졌습니다.

DatePicker에 타이틀로 Select Date라는 문자열을 인자로 받습니다.

View 내에서 생성한 Date 타입의 State 변수를 selection 인자로 바인딩 시켜주죠.

즉, 선택한 날짜가 해당 프로퍼티와 바인딩되어 동기화되겠죠?

 

이제 displayedComponents로 날짜와 시간 등 원하는 선택할 옵션들을 넣어줄 수 있습니다.

 

해당 코드 어떻게 동작하는지 볼까요?

 

 

이렇게 날짜와 시간에 대해 선택할 수 있도록 인터페이스를 제공해줍니다.

 

그럼 이 DatePicker에서 사용할 수 있는 여러 스타일들이 존재하는데 어떤것들이 존재할까요?


DatePickerStyle

우선 DatePickerStyle을 적용시키기 위해서는 DatePicker에 datePickerStyle 모디파이어로 설정할 수 있습니다.

 

DatePicker(
  "Select Date",
  selection: $date,
  displayedComponents: [.date, .hourAndMinute]
)
.datePickerStyle(.compact)

 

간단히 이렇게 인자를 주어 설정할 수 있습니다.

 

제공되는 스타일의 인자로는 총 6가지의 DatePickerStyle이 존재합니다.

 

1️⃣ compact

기본적인 형태로 날짜에 대해 컴팩트 즉, 축소된 사이즈로 영역을 차지하고 보여줍니다.

팝업 형태처럼 나타나는것이죠.

 

2️⃣ graphical

해당 스타일은 그래픽 캘린더 형태로 표시됩니다.

이렇게 팝업이 아닌 캘린더 형태로 그대로 뷰에 노출되죠.

 

이 UI에 나타나는 모습은 실제 OS나 디바이스 종류에 따라 달라질 수 있습니다.

그렇기에 실제 compact 스타일과의 차이는 디스플레이 방식과 상호작용 방식이 다릅니다.

compact 스타일은 조금 더 간결한 UI를 제공하는 반면 graphical 스타일은 더 직관적인 캘린더 인터페이스를 제공하죠.

 

3️⃣ wheel

이름에서도 알 수 있듯 휠 형태의 스타일을 제공합니다.

날짜 및 시간 선택을 위해 스크롤 드래그를 하는 휠 형태로 제공되죠.

 

4️⃣ automatic

시스템이 자동으로 가장 적합하다고 판단하는 스타일로 결정됩니다.

iOS에서는 compact로 노출되더라구요!

 

그리고 이제 남은 두개는 macOS에서만 사용할 수 있는 스타일입니다.


5️⃣ field

6️⃣ stepperField

 

사실 위 macOS에서만 사용할 수 있는 DatePickerStyle은 사용해보지 않아서 추후 macOS를 다루면서 한번 사용하고 포스팅해볼께요!

 

이렇게 우리는 입맛대로 DatePicker를 통해 사용자에게 날짜 및 시간 선택을 위한 인터페이스를 제공하고 정보를 받아올 수 있죠!

꽤 유용하게 쓰이겠죠? 😁

 

근데 이 DatePicker는 날짜 및 시간 외에 다른것을 선택할 수 없잖아요?

그리고 제공되는 형식도 고정이라 더 커스텀한 사용이나 다른 항목들을 같이 선택해야한다면 온전히 DatePicker로 사용하긴 힘들거에요.

 

그래서 이제 알아볼것은 입맛대로 커스텀할 수 있는 Picker 컴포넌트를 알아보겠습니다.


Picker

A control for selecting from a set of mutually exclusive values

 

Picker는 상호 배타적인 값들 중에서 하나만 선택할 수 있도록 제공하는 UI 컴포넌트입니다.

즉, 이러한 기능을 하는 컴포넌트들로는 라디오 버튼, 드롭다운 메뉴, 셀렉트 박스 등 다양하게 꾸려줄 수도 있죠.

그리고 또 오늘 알아볼 Picker를 사용하기도 충분합니다!

 

struct Picker<Label, SelectionValue, Content> where Label : View, SelectionValue : Hashable, Content : View

 

선언은 위와 같습니다.

Label, SelectionValue, Content를 제네릭하게 받는 구조체죠.

 

즉, Label로는 DatePicker에서 봤듯이 타이틀이 들어가게 될것입니다.

SelectionValue로는 선택할 수 있는 값들이 들어가죠!

마지막으로 Content로 이 선택할 값들을 어떻게 보여줄지 나타낼 수 있겠죠?

 

그럼 한번 구현을 통해서 더 자세히 알아보겠습니다!

 

enum ColorSet: String, CaseIterable, Identifiable {
  case green
  case red
  case blue
  
  var backgroundColor: Color {
    switch self {
    case .green:
      return .green
    case .red:
      return .red
    case .blue:
      return .blue
    }
  }
  
  var id: Self { self }
}

 

우선 추후 Picker에서 사용하기전 ColorSet이라는 열거 타입을 만들어줬어요.

이 타입을 통해 만들어진 값들을 Picker에 넣어주고 실제 확인해보려 합니다.

 

그럼 다시 바로 Picker 구현으로 ㄱㄱ

 

struct ContentView: View {
  @State private var selectedColor: ColorSet = .green
  
  var body: some View {
    VStack {
      Rectangle()
        .fill(selectedColor.backgroundColor)
        .frame(width: 200, height: 200)
      
      Picker(
        "Color",
        selection: $selectedColor
      ) {
        ForEach(ColorSet.allCases) { color in
          Text(color.rawValue.capitalized)
        }
      }
    }
  }
}

 

코드를 하나씩 살펴보겠습니다.

우선 위에서 구현한 ColorSet 타입을 갖는 State 프로퍼티인 selectedColor가 존재합니다.

 

그리고 이제 Picker 구현 시 Label을 Color로 정의합니다.

 

⚠️ 여기서 잠깐! ⚠️

 

SwiftUI에서는 사용자 인터페이스의 간결성을 위해 사실 이 Picker에 Label은 화면에서 항상 보이지 않습니다.

즉, 보이고 싶다면 사실 저기서 Label로 선언하는것보다 별도로 Text 같은 컴포넌트로 구성해주는것이 더 적합하죠.

 

그럼 왜 도대체 보이지도 않는데 필요하며 있어야 할까요?

 

그건 바로 화면에서는 보이지 않아도 보이스오버 등 접근성을 위해 존재합니다.

즉, 보이스오버에 의해 해당 Label을 읽을 수 있는것이죠.

이러한 부분들을 느낄때마다 애플의 철학이 마구 담겨있는것 같습니다 😉

 

다시 돌아가서, 이제 selection 인자에 위 selectedColor 프로퍼티를 바인딩 시켜줍니다.

즉, 해당 Picker에서 사용자가 컬러를 선택하면 해당 프로퍼티에 선택한 컬러값이 들어가게 되는것이죠.

 

마지막으로 후행 클로저로 Picker의 컨텐츠들을 어떻게 표현할지 구성해줬습니다.

 

그럼 이제 실제 어떻게 동작할지 볼까요?!

 

 

잘만 동작하지요~

이렇게 선택에 따라 우리가 Rectangle로 만들어 놓은 사각형 뷰의 색상이 잘 변하게 됩니다!

 

Picker를 이용한다면 조금 더 커스텀한 구현이 가능하겠죠?

 

근데 DatePicker에서는 DatePickerStyle이 존재했는데 Picker도 분명 스타일이 있지 않을까요?

 


PickerStyle

func pickerStyle<S>(_ style: S) -> some View where S : PickerStyle

pickerStyle이라는 뷰모디파이어를 이용해 뷰에 구성해줄 수 가 있습니다.

 

즉, 아래와 같이 편하게 사용할 수 있죠.

 

Picker(
  "Color",
  selection: $selectedColor
) {
  ForEach(ColorSet.allCases) { color in
    Text(color.rawValue.capitalized)
  }
}
.pickerStyle(.inline)

 

그럼 지정된 스타일은 어떤 종류들이 있을까요?

 

1️⃣ automatic

DatePickerStyle처럼 시스템에서 환경에 맞춰 스타일을 자동으로 설정해줍니다.

보통 iOS에서는 menu로 설정되는것 같습니다.

 

2️⃣ inline

선택 옵션들을 내포되게 보여주는 인라인 스타일입니다.

 

3️⃣ menu

드롭다운 메뉴로 나타내는 스타일입니다.

 

4️⃣ segmented

세그먼트 스타일로 선택할 수 있는 옵션을 나타내주는 스타일입니다.

 

5️⃣ wheel

inline과 동일하게 내포되어 휠 형태로 나타내주는 스타일입니다.

 

Picker 참 쉽죠!?


마무리

DatePicker와 Picker는 SwiftUI에서 제공하는 기본 컴포넌트로 자주 사용됩니다.

특히 Picker로 커스텀하게 가져갈 수 있는 장점들이 많죠!

 


참고 레퍼런스

https://developer.apple.com/documentation/swiftui/datepicker

 

DatePicker | Apple Developer Documentation

A control for selecting an absolute date.

developer.apple.com

https://developer.apple.com/documentation/swiftui/picker

 

Picker | Apple Developer Documentation

A control for selecting from a set of mutually exclusive values.

developer.apple.com