본 포스팅은 다음 버전을 기준으로 작성되었습니다.

  • Swift 5.3
  • iOS 14.1

Intro

이전 포스트에서 Date 에 관해 알아보았으니 이번에는 사용자가 아이폰에서 날짜를 고를 때 자주 마주치게되는 인터페이스 중 하나인 DatePicker 에 대해 같이 공부해보겠습니다.

iOS 14 가 업데이트 되면서 기존까지와는 다른 스타일의 DatePicker 가 추가되었는데요. 아이폰 기본 알람앱을 자주 사용하는 분이라면 이미 알고 계셨을거에요 ㅎㅎ 아무튼 공부하는 김에 이 새로운 스타일의 DatePicker 도 함께 알아보도록 할게요.


Prerequisite

먼저 실습을 위해 간단하게 ViewController 위에 DatePicker 를 올려놓았습니다.

import UIKit

class ViewController: UIViewController {

    private let datePicker = UIDatePicker()

    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
    }

    // MARK: - UI
    private func configureUI() {
        setAttributes()
        setContraints()
    }

    private func setAttributes() {
        datePicker.preferredDatePickerStyle = .automatic
        datePicker.datePickerMode = .dateAndTime
        datePicker.locale = Locale(identifier: "ko-KR")
        datePicker.timeZone = .autoupdatingCurrent
        datePicker.addTarget(self, action: #selector(handleDatePicker(_:)), for: .valueChanged)
    }

    private func setContraints() {
        view.addSubview(datePicker)
        datePicker.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            datePicker.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
            datePicker.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
            datePicker.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
    }

    // MARK: - Selectors
    @objc
    private func handleDatePicker(_ sender: UIDatePicker) {
        print(sender.date)
    }
}

기본적인 레이아웃 및 Target 작업을 진행해 주었습니다.

DatePickerIntrinsic SizeHeight 값을 갖고 있으므로 따로 높이를 지정해 줄 필요가 없습니다. 즉 넓이를 세팅해주고 Picker 가 올라갈 위치만 잡아주면 된다는거에요. 그리고 DatePickerTarget Action 으로 구현하고자 할 때는 .valueChanged 옵션을 써야한다는 것을 꼭 기억하세요.


Basics

그럼 DatePicker 에서 사용할 수 있는 기본적인 method 에 관해 함께 공부해보겠습니다.

DatePicker Style

iOS 14가 업데이트 되면서 DatePicker 에 새로운 스타일이 추가되었다고 했는데요. 먼저 어떤 스타일들이 있는지 함께 확인해보도록 하겠습니다. 종류는 총 3가지가 존재하며 기본값은 .automatic 으로 되어있어 시스템이 현재 뷰에 가장 알맞은 스타일을 선택해 준다고해요. 자동으로하면 나는 항상 compact 만 되는 것 같던데??

datePicker.preferredDatePickerStyle = .automatic

일단은 .automatic 상태로 코드를 작성해 놓았습니다. 이제 이걸 하나씩 바꿔가며 어떻게 바뀌는지 살펴볼거에요.

.compact

아무것도 설정하지 않으면 이게 기본값처럼 실행되는 것으로 봐서는 이게 Apple 에서 가장 추천하는 최신 스타일이 아닌가해요. 다른 DatePicker 스타일에 비해서 정말 심플하기도 하고, 공간도 덜 차지한다는 장점이 있는 디자인입니다. 시간이 적혀있는 label 을 사용자가 탭하여 원하는 값으로 수정할 수 있습니다.

compact 스타일

.inline

이건 .compact 스타일에서 탭하면 보이는 달력을 미리 펼쳐놓은 형태에요. 그동안 Apple 에서 기본적으로 제공하는 캘린더가 없었다고 생각해보면, 이걸 어떻게 사용하느냐에 따라서 어느정도 간단한 기능의 캘린더는 대체할 수도 있지 않을까 생각이 드네요.

inline 스타일

.wheel

익숙한 스타일이죠. 우리가 자주 썼었던 예전 스타일의 DatePicker 도 계속 사용할 수 있습니다.

wheel 스타일

이제 앱을 실행시켜서 원하는 날짜를 DatePicker 에서 골라보세요. Console 에 시간이 정상적으로 출력됩니다. 근데 혹시 한가지 이상한 점을 눈치채셨나요?

콘솔에 출력되는 시간이 DatePicker 에서 고른 시각과 다르게 나오고 있어요. 이건 코드에 잘못된 부분이 있는게 아니라 기본적으로 표시되는 시간이 GMT Format 을 따르기 때문인데요.

나중에 NSDateFormatter 를 사용해서 우리가 원하는 시간대로 출력되도록 바꿔줄 수 있습니다. DateFormatter 까지 알아보려면 포스트가 너무 길어지니 일단 지금은 그냥 넘어가고 다음에 더 자세히 알아보기로 해요 ㅎㅎ


DatePicker Mode

.preferredDatePickerStyle 이 새롭게 제공되는 기능이라면, 이전부터 제공되던 .datePickerMode 라는 기능도 있습니다.

모드로는 총 4가지의 옵션이 존재합니다.

  • .dateAndTime
  • .date
  • .time
  • .countDownTimer

처음 3 가지는 이름만 봐도 비슷하다는게 느껴지나요? 날짜와 시간을 모두 고르게할지 날짜 혹은 시간만 선택할 수 있도록 할지 결정해주는 것입니다. .countDownTimer 만 조금 다른데요. 이건 method 이름처럼 사용자에게 타이머 기능을 제공하고자 할 때 사용할 수 있는 인터페이스 입니다.


Locale

.localeDatePicker 에 사용하는 국가를 입력할 수 있습니다. 아무런 설정도 건드리지 않으면 아이폰 기본설정을 사용합니다.

datePicker.locale = Locale(identifier: "ko-KR")

한국으로 설정이 필요하다면 이렇게 코드를 입력하세요.


minuteInterval

.minuteInterval 은 사용자가 스크롤을 돌려 시간을 설정할 때 나타나는 분 단위 간격을 조절할 수 있습니다. 기본값은 1분으로 되어있고요. 최대 30분까지 입력이 가능합니다. 이 설정을 사용할 때는 1시간은 60분이니까 60의 약수 내에서 입력하도록 하세요.

datePicker.minuteInterval = 5

이렇게 설정하면 분 단위 설정이 5분 간격으로 가능합니다.


Date

최초에 선택되어 있는 날짜를 설정할 수가 있는 method 에요! 단 DatePicker 의 Mode 가 .countDownTimer 로 설정되어 있을 때는 작동하지 않습니다.

datePicker.date = Date(timeIntervalSinceNow: -3600 * 24 * 3)

이렇게 코드를 입력하면 DatePicker 가 현재 날짜를 기준으로 3일 전의 날짜로 선택되어 시작합니다.


setDate

.date 의 역할을 포함하고, 추가로 애니메이션 작동 여부를 설정하는 역할을 합니다.

datePicker.setDate(Date(), animated: true)

여러가지 실험을 해봤지만 어느 부분에서 애니메이션이 작동하는지 확인하기가 어렵더라고요… 나중에 혹시 알아내게 된다면 업데이트 하겠습니다.. 아무튼 이 애니메이션의 기본값은 false 라고 합니다.


minimumDate, maximumDate

사용자가 선택할 수 있는 날짜나 시간을 한정할 수 있게 도와주는 method 입니다.

.wheel 모드에서는 사용자가 우리가 지정해놓은 한계 이상으로 스크롤을 했을 경우 처음 기본값 상태로 되돌아오게 됩니다. 그리고 새로나온 .compact.inline 모드에서는 선택할 수 있는 날짜가 연한 회색으로 비활성화되는 방식으로 사용자에게 이 날짜는 선택할 수 없다는 것을 직관적으로 알 수 있게 합니다.

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())

datePicker.maximumDate = maxDate
datePicker.minimumDate = minDate

위 코드를 입력하면 현재 날짜를 기준으로 앞뒤 10일까지만 선택이 가능해집니다.

시뮬레이터 실행결과

현재 날짜를 기준으로 10일 이전의 날짜가 회색으로 표시되며 비활성화 된 것이 보이죠? ㅎㅎ


Calendar, timeZone

.calendar, .timeZone 에 대한 설정은 스토리보드에서는 불가능하고 코드로만 설정이 가능한데요. 저는 코드파라 사실 불편함이 없더라고요 ㅎㅎㅎ 아무튼 이 설정에 대해서는 자세히 설명하지 않겠습니다.

Calendar 가 아직 익숙하지 않다면 UIKit - Calendar 와 Date 기초 익히기 포스팅을 참고해주세요.


Wrap Up

오늘은 iOS 14 에서 새롭게 리뉴얼된 DatePicker 에 대해 공부해보았는데요. 날짜를 다루는데 어느정도 익숙한 분이라면 크게 어렵게 느낄만한 부분은 없었던 것 같네요. 이렇게 하나하나 파헤쳐보는게 바로 개발의 맛 아닐까요?

다음 포스트에서는 오늘 이런 모드가 있다 얘기만 하고 넘어간 DatePicker.countDownTimer 모드를 사용해 타이머를 만드는 방법에 대해 알아보도록 하겠습니다~!