[SwiftUI] Picker 맛보기

Picker, DatePicker, ColorPicker 에 대해 간단히 살펴봅시다

naljin
9 min readAug 1, 2021

Picker

swiftUI에서는 위와 같은 picker를 해당 코드로 만들 수 있습니다.

enum Flavor: String, CaseIterable, Identifiable {
case chocolate
case vanilla
case strawberry

var id: String { self.rawValue }
}

struct FlavorPicker: View {
@State private var selectedFlavor = Flavor.chocolate

var body: some View {
VStack {
Picker("Flavor", selection: $selectedFlavor) {
ForEach(Flavor.allCases) { flavor in
Text(flavor.rawValue)
.tag(flavor)
}
}
Text("Selected flavor: \(selectedFlavor.rawValue)")
}
}
}

피커 쪽만 떼어서 볼까요?

Picker("Flavor", selection: $selectedFlavor) {
ForEach(Flavor.allCases) { flavor in
Text(flavor.rawValue)
.tag(flavor)
}
}

꽤나 간단합니다. 이때 “흠.. 피커에서 어떤 요소를 클릭했는지 어떻게 감지하지?” 라는 의문점이 들 수 있는데요! 여기서 tag(_:) modifier를 주목해봅시다.

Text 마다 붙인 태그 값은, selection 파라미터로 넘겨진 $selectedFlavor 값과 연관됩니다. 만약 피커에서 chocolate을 선택하면, chocolate에 해당하는 tag 값으로 $selectedFlavor 이 변화됩니다.

사실 ForEach 로 Picker를 생성을 하면 내부의 id를 이용해서 자동으로 tag를 어사인 해줍니다. (여기선 FlavorIdentifiable protocol을 따르고 있기 때문에 가능)

pickerStyle

pickerStyle(_:) modifier를 통해서 피커의 스타일 (automatic, wheel, menu, segmented, inline, radioGroup) 을 지정할 수 있습니다.

Picker(~~~)
.pickerStyle(.wheel)

다만 Xcode13.0 이전의 환경을 사용하고 있으신 분들은 .pickerStyle(InlinePickerStyle())요런식으로 해당하는 struct를 생성해서 넣어줘야할 것 같습니다. (왜냐면 Xcode 12.5 에서는 .inline 이 안먹혔거든여)

하나씩 어떤 스타일이 적용되는지 살펴봅시다.

automatic

picker 의 context에 따라 달라지는 default 스타일입니다.

wheel

선택한 옵션과 몇 가지 인접 옵션을 표시하는 휠에 옵션을 표시하는 스타일입니다.

menu

사용자가 버튼을 누를 때 메뉴로 옵션을 표시하거나, 더 큰 메뉴에 중첩될 때 하위 메뉴로 옵션을 표시하는 스타일입니다.

segmented
segmented control에 옵션을 표시하는 스타일입니다.

inline

각 옵션이 현재 컨테이너의 다른 view들과 함께 inline 으로 표시 됩니다. picker가 List 안에 있을 때 차이점을 확인 할 수 있습니다.

List {
Picker("Flavor", selection: $selectedFlavor) {
ForEach(Flavor.allCases) { flavor in
Text(flavor.rawValue)
.tag(flavor)
}
}
.pickerStyle(.inline)

Text("Selected flavor: \(selectedFlavor.rawValue)")
}

radioGroup

라디오 버튼의 그룹으로 옵션을 표시하는 스타일입니다. 하지만 macOS 에서만 사용 가능합니다.

macOS

DatePicker

DatePicker도 그냥 picker 와 마찬가지로 간단하게 구현할 수 있습니다.

@State private var today = Date()var body: some View {
DatePicker(
"Start Date",
selection: $today,
in: dateRange,
displayedComponents: [.date, .hourAndMinute]
)
}

추가로 date의 범위도 지정할 수 있습니다

//범위 지정
var dateRange: ClosedRange<Date> {
let min = Calendar.current.date(byAdding: .year, value: -1, to: today)!
let max = Calendar.current.date(byAdding: .year, value: 1, to: today)!
return min...max
}
var body: some View {
DatePicker(
"Start Date",
selection: $today,
in: dateRange, //범위 파라미터 추가
displayedComponents: [.date, .hourAndMinute]
)
}

datePickerStyle

datePickerStyle(_:) view modifier를 통해서 date 피커의 스타일 (automatic, compact, graphical, wheel, stepperField, field) 을 지정할 수 있습니다.

DatePicker(~~)
.datePickerStyle(.compact)

automatic

date picker의 기본 스타일입니다. 이걸로 지정하면 compact 랑 동일하게 나오네여

compact

component 를 compact하고 textual한 형식으로 표시하는 스타일입니다.

graphical

interactive한 달력 또는 시계를 표시하는 스타일입니다.

wheel

휠에서 각 component 를 column으로 표시하는 스타일입니다.

stepperField

편집 가능한 필드에 component를 표시하는 시스템 스타일이며, 선택한 component 를 증가/감소할 수 있는 스텝퍼가 있습니다. 하지만 macOS 에서만 사용 가능합니다.

field

편집 가능한 필드에 component 를 표시하는 스타일입니다. 하지만 macOS 에서만 사용 가능합니다. 이곳에 따르면 해당 필드를 클릭하면 GraphicalStyle subview로 팝업이 나타난다고 합니다.

ColorPicker

ColorPicker도 다른 피커들과 마찬가지로 간단하게 구현할 수 있습니다.

struct FormattingControls: View {
@State private var bgColor =
Color(.sRGB, red: 0.98, green: 0.9, blue: 0.2)
var body: some View {
VStack {
ColorPicker("Alignment Guides", selection: $bgColor)
}
}
}

color picker는 현재 선택된 색상을 표시하며, 사용자가 새 색상을 선택할 수 있는 더 큰 시스템 color picker를 표시합니다.

opacity를 지원하지 않으려면 supportOpacity 매개 변수를 false로 설정합니다.

ColorPicker("Alignment Guides",
selection: $bgColor,
supportsOpacity: false)

--

--