DatePicker는 날짜와 시간을 선택할 때 사용하는 UI입니다.
알람을 설정할 때 가장 많이 봤던 UI인데 알아보도록 하겠습니다.
DatePicker 알아보기
화면을 알람앱 비슷하게 만들어 봤습니다!

DatePicker는 화면에 바로 올려 놓으면 사진처럼 화면에 보여집니다.
키보드에 뜨는 어플들도 있고 몇가지 방식으로 DatePicker를 사용할 수 있습니다.

Inspector에 있는 속성들을 하나씩 살펴보겠습니다.
[Preferred Style]
DatePicker의 스타일을 표시합니다. 현재 상태는 Wheels
.automatic, wheels, compact, inline 4개가 존재하고, automatic은 3개중 가장 적합한 걸 알아서 골라 보여준다고 합니다.


compact는 저 작은 박스를 누르면 Picker가 열리게 되고
inline은 picker가 바로 보여지게 됩니다.
근데 여기서 조금 다른점
시간만 설정하게 되어있을 때 compact, inline은 둘 다 compact와 같이 picker가 열리는 방식으로 동작합니다.
[Mode]
Date, Time, DateAndTime, CountDownTimer가 존재합니다.
[Locale]
DatePicker 사용시 표시될 지역을 설정합니다.
Default로 되어 있을 때는 핸드폰의 설정에 따릅니다.
[Interval, Count-Down]
Date Mode에서는 보여지지 않는 속성입니다.
Interval은 시간을 조정할 때 몇 분씩 조정할 것 인가
Count-Down은 기본 CountDown 설정을 할 수 있습니다.
[Date]
DatePicker가 표시될 때 현재 날짜를 표시하거나 사용자 지정 날짜를 보여줍니다.
Current Date, Custom이 존재합니다.
Minimum, Maximum Date 설정으로 선택 가능한 날짜도 설정이 가능합니다.
코드로 설정 하는것도 알아보겠습니다.
self.datePicker.datePickerMode = .date
self.datePicker.preferredDatePickerStyle = .wheels
self.datePicker.locale = Locale(identifier: "ko-KR")
속성 설정 중 Locale 설정을 어떻게 해야할지 몰랐는데 생각보다 간단했습니다.
identifier에 한국은 "ko-KR" 미국은? "en-US"
아래 표를 만들어놨습니다.
| af | 남아공 공용어 |
| af-ZA | 아프리칸스어(남아프리카 공화국) |
| sq | 알바니아어 |
| sq-AL | 알바니아어(알바니아) |
| ar | 아랍어 |
| ar-DZ | 아랍어(알제리) |
| ar-BH | 아랍어(바레인) |
| ar-EG | 아랍어(이집트) |
| ar-IQ | 아랍어(이라크) |
| ar-JO | 아랍어(요르단) |
| ar-KW | 아랍어(쿠웨이트) |
| ar-LB | 아랍어(레바논) |
| ar-LY | 아랍어(리비아) |
| ar-MA | 아랍어(모로코) |
| ar-OM | 아랍어(오만) |
| ar-QA | 아랍어(카타르) |
| ar-SA | 아랍어(사우디아라비아) |
| ar-SY | 아랍어(시리아) |
| ar-TN | 아랍어(튀니지) |
| ar-AE | 아랍어(아랍에미리트) |
| ar-YE | 아랍어(예멘) |
| hy | 아르메니아어 |
| hy-AM | 아르메니아어(아르메니아) |
| az | 아제리어 |
| az-Cyrl-AZ | 아제리어(아제르바이잔, 키릴 자모) |
| az-Latn-AZ | 아제리어(아제르바이잔, 라틴 문자) |
| eu | 바스크어 |
| eu-ES | 바스크어(바스크) |
| be | 벨로루시어 |
| be-BY | 벨로루시어(벨로루시) |
| bg | 불가리아어 |
| bg-BG | 불가리아어(불가리아) |
| ca | 카탈로니아어 |
| ca-ES | 카탈로니아어(카탈로니아) |
| zh-HK | 중국어(홍콩 특별 행정구, 중국) |
| zh-MO | 중국어(마카오 특별 행정구) |
| zh-CN | 중국어(중국) |
| zh-Hans | 중국어(간체) |
| zh-SG | 중국어(싱가포르) |
| zh-TW | 중국어(대만) |
| zh-Hant | 중국어(번체) |
| hr | 크로아티아어 |
| hr-BA | 크로아티아어(보스니아 헤르체고비나) |
| hr-HR | 크로아티아어(크로아티아) |
| cs | 체코어 |
| cs-CZ | 체코어(체코) |
| da | 덴마크어 |
| da-DK | 덴마크어(덴마크) |
| dv | 디베히어 |
| dv-MV | 디베히어(몰디브) |
| nl | 네덜란드어 |
| nl-BE | 네덜란드어(벨기에) |
| nl-NL | 네덜란드어(네덜란드) |
| en | 영어 |
| en-AU | 영어(오스트레일리아) |
| en-BZ | 영어(벨리즈) |
| en-CA | 영어(캐나다) |
| en-029 | 영어(카리브 해) |
| en-IE | 영어(아일랜드) |
| en-JM | 영어(자메이카) |
| en-NZ | 영어(뉴질랜드) |
| en-PH | 영어(필리핀) |
| en-ZA | 영어(남아프리카 공화국) |
| en-TT | 영어(트리니다드 토바고) |
| en-GB | 영어(영국) |
| en-US | 영어(미국) |
| en-ZW | 영어(짐바브웨) |
| et | 에스토니아어 |
| et-EE | 에스토니아어(에스토니아) |
| fo | 페로스어 |
| fo-FO | 페로어(페로 제도) |
| fa | 페르시아어 |
| fa-IR | 페르시아어(이란) |
| fi | 핀란드어 |
| fi-FI | 핀란드어(핀란드) |
| fr | 프랑스어 |
| fr-BE | 프랑스어(벨기에) |
| fr-CA | 프랑스어(캐나다) |
| fr-FR | 프랑스어(프랑스) |
| fr-LU | 프랑스어(룩셈부르크) |
| fr-MC | 프랑스어(모나코) |
| fr-CH | 프랑스어(스위스) |
| gl | 갈리시아어 |
| gl-ES | 갈리시아어(스페인) |
| ka | 그루지야어 |
| ka-GE | 그루지야어(그루지야) |
| de | 독일어 |
| de-AT | 독일어(오스트리아) |
| de-DE | 독일어(독일) |
| de-DE_phoneb | 독일어(독일, 전화 번호부 정렬) |
| de-LI | 독일어(리히텐슈타인) |
| de-LU | 독일어(룩셈부르크) |
| de-CH | 독일어(스위스) |
| el | 그리스어 |
| el-GR | 그리스어(그리스) |
| gu | 구자라트어 |
| gu-IN | 구자라트어(인도) |
| he | 히브리어 |
| he-IL | 히브리어(이스라엘) |
| hi | 힌디어 |
| hi-IN | 힌디어(인도) |
| hu | 헝가리어 |
| hu-HU | 헝가리어(헝가리) |
| is | 아이슬란드어 |
| is-IS | 아이슬란드어(아이슬란드) |
| id | 인도네시아어 |
| id-ID | 인도네시아어(인도네시아) |
| it | 이탈리아어 |
| it-IT | 이탈리아어(이탈리아) |
| it-CH | 이탈리아어(스위스) |
| ja | 일본어 |
| ja-JP | 일본어(일본) |
| kn | 카나다어 |
| kn-IN | 카나다어(인도) |
| kk | 카자흐어 |
| kk-KZ | 카자흐어(카자흐스탄) |
| kok | 콘칸어 |
| kok-IN | 콘칸어(인도) |
| ko | 한국어 |
| ko-KR | 한국어(대한민국) |
| ky | 키르기스어 |
| ky-KG | 키르기스어(키르기스스탄) |
| lv | 라트비아어 |
| lv-LV | 라트비아어(라트비아) |
| lt | 리투아니아어 |
| lt-LT | 리투아니아어(리투아니아) |
| mk | 마케도니아어 |
| mk-MK | 마케도니아어(마케도니아, FYROM) |
| ms | 말레이어 |
| ms-BN | 말레이어(브루나이) |
| ms-MY | 말레이어(말레이시아) |
| mr | 마라티어 |
| mr-IN | 마라티어(인도) |
| mn | 몽골어 |
| mn-MN | 몽골어(몽골) |
| no | 노르웨이어 |
| nb-NO | 노르웨이어(복말, 노르웨이) |
| nn-NO | 노르웨이어(니노르스크, 노르웨이) |
| pl | 폴란드어 |
| pl-PL | 폴란드어(폴란드) |
| pt | 포르투갈어 |
| pt-BR | 포르투갈어(브라질) |
| pt-PT | 포르투갈어(포르투갈) |
| pa | 펀잡어 |
| pa-IN | 펀잡어(인도) |
| ro | 루마니아어 |
| ro-RO | 루마니아어(루마니아) |
| ru | 러시아어 |
| ru-RU | 러시아어(러시아) |
| sa | 산스크리트어 |
| sa-IN | 산스크리트어(인도) |
| sr-Cyrl-CS | 세르비아어(세르비아, 키릴 자모) |
| sr-Latn-CS | 세르비아어(세르비아, 라틴 문자) |
| sk | 슬로바키아어 |
| sk-SK | 슬로바키아어(슬로바키아) |
| sl | 슬로베니아어 |
| sl-SI | 슬로베니아어(슬로베니아) |
| es | 스페인어 |
| es-AR | 스페인어(아르헨티나) |
| es-BO | 스페인어(볼리비아) |
| es-CL | 스페인어(칠레) |
| es-CO | 스페인어(콜롬비아) |
| es-CR | 스페인어(코스타리카) |
| es-DO | 스페인어(도미니카 공화국) |
| es-EC | 스페인어(에콰도르) |
| es-SV | 스페인어(엘살바도르) |
| es-GT | 스페인어(과테말라) |
| es-HN | 스페인어(온두라스) |
| es-MX | 스페인어(멕시코) |
| es-NI | 스페인어(니카라과) |
| es-PA | 스페인어(파나마) |
| es-PY | 스페인어(파라과이) |
| es-PE | 스페인어(페루) |
| es-PR | 스페인어(푸에르토리코) |
| es-ES | 스페인어(스페인) |
| es-ES_tradnl | 스페인어(스페인, 전통 정렬) |
| es-UY | 스페인어(우루과이) |
| es-VE | 스페인어(베네수엘라) |
| sw | 스와힐리어 |
| sw-KE | 스와힐리어(케냐) |
| sv | 스웨덴어 |
| sv-FI | 스웨덴어(핀란드) |
| sv-SE | 스웨덴어(스웨덴) |
| syr | 시리아어 |
| syr-SY | 시리아어(시리아) |
| ta | 타밀어 |
| ta-IN | 타밀어(인도) |
| tt | 타타르어 |
| tt-RU | 타타르어(러시아) |
| te | 텔루구어 |
| te-IN | 텔루구어(인도) |
| th | 태국어 |
| th-TH | 태국어(태국) |
| 터키어 | |
| tr-TR | 터키어(터키) |
| uk | 우크라이나어 |
| uk-UA | 우크라이나어(우크라이나) |
| ur | 우르두어 |
| ur-PK | 우르두어(파키스탄) |
| uz | 우즈베크어 |
| uz-Cyrl-UZ | 우즈베크어(우즈베키스탄, 키릴 자모) |
| uz-Latn-UZ | 우즈베크어(우즈베키스탄, 라틴 문자) |
| vi | 베트남어 |
| vi-VN |
베트남어(베트남) |
//Picker 시간을 조정할 때 간격
datePicker.minuteInterval = 5
//Picker가 열렸을 때 표시될 날짜
datePicker.date = Date(timeIntervalSinceNow: -3600 * 24 * 3) //3일 전 날짜로 설정됨
//날짜 선택 제한 설정
var components = DateComponents()
components.day = 10
let maxDate = Calendar.autoupdatingCurrent.date(byAdding: components, to: Date())
components.day = -10
let minDate = Calendar.autoupdatingCurrent.date(byAdding: components, to: Date())
//현재를 기준으로 +-10일
datePicker.maximumDate = maxDate
datePicker.minimumDate = minDate
Inspector에서 설정했던 속성을 코드로도 간단하게 설정 할 수 있습니다!
datePicker.setDate(Date(timeIntervalSinceNow: -3600 * 24 * 3), animated: true)
Date 설정은 Method도 존재합니다. Animation 설정 할 수 있는데 기본적으로 false라고 합니다.
DatePicker 사용
DatePicker를 사용해서 얻을 수 있는 건 당연히 날짜 또는 시간입니다.
간단하게 포맷을 알아보고 데이터를 가져오는 걸 알아보겠습니다.
먼저 클래스에서 DatePicker의 이벤트를 만들어줘야 합니다.
addTarget을 사용
self.datePicker.addTarget(self, action: #selector(datePickerValueDidChange(_:)), for: .valueChanged)
값이 변경되었을 때 함수를 호출되게 만들었습니다!
나중에 addTarget도 제대로 알아봐야 할 것 같아요...
action파라미터는 obj-c로 만들어진 함수를 넣어야 하기 때문에? obj-c로 컨버팅 가능하게 swift로 함수를 작성해 줍니다.
그냥 함수를 만들어서 넣어주면 이런 오류 문구가 뜹니다.

함수 앞에 @objc를 붙이면 obj-c로 포팅? 컨버팅? 이 되어 들어가집니다.
@objc private func datePickerValueDidChange(_ datePicker: UIDatePicker) {
let formmater = DateFormatter()
formmater.dateFormat = "yyyy년 MM월 dd일 (EEEEE)"// E다섯개는 요일을 하나만 나타냄
formmater.locale = Locale(identifier: "ko-KR")
self.diaryDate = datePicker.date
self.dateField.text = formmater.string(from: datePicker.date)
self.dateField.sendActions(for: .editingChanged) //editing화면이 됐을때
}
먼저 날짜만 가져온다는 설정으로 코드를 작성한 것입니다.
DateFormat과 지역을 설정하고 값을 받아 뿌려줍니다.

사진을 보니까... E 하나만 써도 요일은 하나만 잘 나오겠네요
또는 DateFormatter에서 기본제공하는 포맷을 사용해도 됩니다.
formmater.dateStyle = .long
formmater.timeStyle = .long


둘 다 플래그가 같기에 한번에 알아보겠습니다.
full 형식
2022년 1월 23일 목요일
오전 1시 6분 10초 대한민국 표준시
long 형식
2022년 1월 23일
오전 1시 6분 10초 GMT+9
medium 형식
2022. 1. 23
오전 1:06:10
short 형식
2022. 1. 23
오전 1:06
none 형식
아무것도 안나옵니다.
위와 같은 형식으로 출력되게 포맷이 맞춰집니다.
마지막 하나 더!
DatePicker를 에디터 화면(키보드 나오는 화면)에 띄우고 싶다면?
dateField.inputView = self.datePicker
입력 가능한 UI에 inputView 메서드를 사용해서 datePicker를 넣어주면 됩니다.
