[TIL] PickerView를 사용해보자

한철희·2024년 5월 28일
0

TIL

목록 보기
47/57

이번 프로젝트 때 알람앱을 구현하면서
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
        }
    }
}
profile
초보 개발자 살아남기

0개의 댓글