이번 프로젝트 때 알람앱을 구현하면서
PickerView
를 사용해봤다
이번에 처음 사용해보는 기능인 만큼 작성법을
적어보면서 정리해두려고한다
일단 작업한 페이지에서 PickerView
관련 부분만 가져왔습니다
import UIKit
class SetAlarmVC: UIViewController {
// MARK: - variable
let amPm = ["오전", "오후"]
let hours = Array(1...12).map { "\($0)" }
let minutes = Array(0...59).map { String(format: "%02d", $0) }
let pickerView = UIPickerView()
let label = UILabel()
let numberLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
setupPickerView()
setInitialPickerViewTime()
}
// MARK: - func
func setupLabels() {
// label 설정
label.text = "선택된 시간대"
label.textAlignment = .center
view.addSubview(label)
// numberLabel 설정
numberLabel.text = "선택된 숫자"
numberLabel.textAlignment = .center
view.addSubview(numberLabel)
label.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.bottom.equalToSuperview().offset(-200)
make.width.equalTo(200)
make.height.equalTo(40)
}
numberLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.bottom.equalTo(label.snp.top).offset(-20)
make.width.equalTo(200)
make.height.equalTo(40)
}
}
func setupPickerView() {
// pickerView 설정
view.addSubview(pickerView)
// pickerView의 delegate와 dataSource 설정
pickerView.delegate = self
pickerView.dataSource = self
// SnapKit을 사용하여 pickerView의 위치와 크기를 설정
pickerView.snp.makeConstraints { make in
make.centerX.equalToSuperview() // 중앙 정렬
make.top.equalToSuperview().offset(100) // 상단으로부터 100의 거리에 위치
make.left.equalToSuperview().offset(20) // 왼쪽에서 20만큼 간격
make.right.equalToSuperview().offset(-20)
make.height.equalTo(200) // 높이는 200으로 설정
}
}
func setInitialPickerViewTime() {
// 현재 시간을 가져옵니다.
let currentDate = Date()
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute], from: currentDate)
// pickerView의 시간 및 분 구성 요소의 초기 선택된 행을 설정합니다.
if let hour = components.hour, let minute = components.minute {
// 시간을 12시간 형식으로 변환하여 pickerView의 시간 컴포넌트 초기 선택 행을 설정
let displayHour = hour % 12 == 0 ? 12 : hour % 12 // 0시를 12시로 표시
pickerView.selectRow(displayHour - 1, inComponent: 1, animated: false) // displayHour - 1: 인덱스가 0부터 시작하기 때문에 조정
// 분을 1분 단위로 설정: 분에 해당하는 컴포넌트의 정확한 행을 선택
pickerView.selectRow(minute, inComponent: 2, animated: false) // 분을 직접 사용하여 해당하는 행 선택
// AM/PM 설정
let selectedAmPmIndex = hour < 12 ? 0 : 1
pickerView.selectRow(selectedAmPmIndex, inComponent: 0, animated: false)
// 레이블 업데이트
label.text = amPm[selectedAmPmIndex]
numberLabel.text = String(format: "%02d", displayHour)
}
}
}
// MARK: - UIPickerViewDataSource
extension SetAlarmVC: UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
let infiniteRows = 10000 // 순환을 위한 충분히 큰 값
if component == 0 {
return amPm.count
} else {
// 시간과 분을 위한 순환 행의 수
return infiniteRows
}
}
// pickerView에서 보여주고 싶은 아이템의 제목
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return amPm[row]
} else if component == 1 {
// 시간 순환
let actualHour = hours[row % hours.count] // modulo 연산으로 순환 효과 구현
return actualHour
} else {
// 분 순환
let actualMinute = minutes[row % minutes.count] // modulo 연산으로 순환 효과 구현
return actualMinute
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
}
// MARK: - UIPickerViewDelegate
extension SetAlarmVC: UIPickerViewDelegate {
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
label.text = amPm[row]
} else if component == 1 {
// 시간 선택 시
let actualHour = hours[row % hours.count] // modulo 연산으로 실제 시간 계산
numberLabel.text = actualHour
} else {
// 분 선택 시
let actualMinute = minutes[row % minutes.count] // modulo 연산으로 실제 분 계산
numberLabel.text = actualMinute
}
}
}