sladuf
200
sladuf
์ „์ฒด ๋ฐฉ๋ฌธ์ž
์˜ค๋Š˜
์–ด์ œ
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (83)
    • ๐Ÿ“š Programming (32)
      • Swift (13)
      • JAVA (2)
      • Python (6)
      • SQL (6)
      • Web (5)
    • ๐Ÿ“ฑ iOS (25)
      • Base (7)
      • SwiftUI (9)
      • UIKit (7)
      • ์ธ๊ฐ• & ์ฑ… (2)
    • ๐Ÿ”— Algorithm (20)
      • Python (12)
      • Swift (3)
      • Tip (5)
    • ๐Ÿ—‚ ETC (6)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ํƒœ๊ทธ
  • ๋ฐฉ๋ช…๋ก

๊ณต์ง€์‚ฌํ•ญ

์ธ๊ธฐ ๊ธ€

ํƒœ๊ทธ

  • Swift
  • ์Šค์œ„ํ”„ํŠธ

์ตœ๊ทผ ๋Œ“๊ธ€

์ตœ๊ทผ ๊ธ€

ํ‹ฐ์Šคํ† ๋ฆฌ

๊ธ€์“ฐ๊ธฐ ์„ค์ •
hELLO ยท Designed By ์ •์ƒ์šฐ.
sladuf

200

[UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (3/3)
๐Ÿ“ฑ iOS/UIKit

[UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (3/3)

2023. 4. 3. 01:59

 

 

Rx๋ฅผ ๋ชจ๋ฅด์‹ ๋‹ค๋ฉด ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿฅน

 


๋“œ๋””์–ด ๋งˆ์ง€๋ง‰ ๊ด€๋ฌธ.. ๋…„,์›”์„ ๊ด€์ฐฐํ•˜์—ฌ ์ผ ์ˆ˜๋ฅผ ์ •ํ•˜์ž!

 

 

์ผ๋‹จ ๋‚˜๋Š” ์ง€๊ธˆ

์ด๊ฑธ ๋งŒ๋“œ๋Š” ์ค‘์ด๋‹ค

 

 

 

๋…„,์›”์€ ์˜์กด์„ฑ์ด ์—†์ง€๋งŒ, '์ผ'์€ ๋…„,์›”์— ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.

1์›”์€ 31์ผ๊นŒ์ง€, 2์›”์€ 28์ผ๊นŒ์ง€ ๋ญ์ด๋Ÿฐ๊ฑฐ ~..

 

๊ทธ๋ž˜์„œ '์ผ'์€ ๋…„,์›”์ด ๋ฐ”๋€Œ๋ฉด reset์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์˜ˆ๋ฅผ๋“ค์–ด 2023๋…„1์›”31์ผ์„ ๋งŒ๋“ค์–ด์ค€ ์ƒํƒœ์—์„œ '์›”'์„ 2์›”๋กœ ๋ฐ”๊พธ๋ฉด 31์ผ์€ ์—†๊ธฐ ๋•Œ๋ฌธ์—!!

 

 

๊ทธ๋ž˜์„œ customPicker์—์„œ ๋ญ”๊ฐ€๋ฅผ ์„ ํƒํ–ˆ์„ ๋•Œ ๊ด€์ฐฐํ•˜๋Š” ๋Œ€์ƒ์—๊ฒŒ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋„๋ก

Rx๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์ ์šฉํ–ˆ๋‹ค.

 

(1/3)์—์„œ ๋งŒ๋“ค์—ˆ๋˜ CustomPickerButton์— ์ถ”๊ฐ€ํ•œ ๋ถ€๋ถ„!

public class CustomPickerButton: UIButton {

    var changed = PublishRelay<String>()

    //data ์„ ํƒ์‹œ ๋™์ž‘ํ•  event
    public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if data?[row] == "" {
            label.text = placeholder
        }
        else{
            label.text = data?[row]
        }
        changed.accept(label.text ?? placeholder)
    }
}

 

changed๋Š” PublishRelay๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” ๋‹ค์ด์–ด๊ทธ๋žจ ๋ณด๋ฉด ๋  ๋“ฏ..?

Subject๋ž‘ ์›๋ฆฌ๋Š” ๋˜‘๊ฐ™๊ณ , ์ฐจ์ด์ ์€ next๋งŒ ๋ฐฉ์ถœํ•œ๋‹ค๋Š”๊ฑฐ!

 

 

 

๊ทธ๋ฆฌ๊ณ  CustomDatePicker์—์„œ ๋งŒ๋“ค์—ˆ๋˜ dataSetting()์„ ์ˆ˜์ •ํ•ด์ค๋‹ˆ๋‹ค!!

//CustomDatePicker.swift
func dataSetting(){
    var years = [String]()
    for y in 1970...dateFormatter("yyyy") {
        years.append(String(y))
    }
    yearPicker.setData(data: years.reversed())

    var months = [String]()
    for m in 1...12{
        months.append(String(m))
    }
    monthPicker.setData(data: months)
}

dataSetting()์—๋Š” ์˜์กด์„ฑ์ด ์—†๋Š” ๋…„,์›”๋งŒ settingํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•œ ๋ฒˆ settingํ•˜๊ณ  ๋ฐ”๋€” ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค. DatePicker๊ฐ€ ์ดˆ๊ธฐํ™” ๋  ๋•Œ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋˜๊ฒ ์ฃ ?

 

๋…„๋„๋Š” ๋งˆ์Œ๋Œ€๋กœ ์ •ํ•ด๋„ ๋˜๋Š”๋ฐ,

์ €๋Š” 1970๋…„๋„๋ถ€ํ„ฐ ํ˜„์žฌ ๋…„๋„๊นŒ์ง€ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๊ณ ,

์ƒ๋Œ€์ ์œผ๋กœ ์ตœ๊ทผ์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค

 

๊ทธ๋Ÿผ ์ด์ œ '์ผ'์„ settingํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

'์ผ'์€ ๋…„,์›”์„ ์•Œ์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋…„, ์›”์„ ๊ฐ€์ ธ์˜ฌ getData()ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค!!

CustomPickerButton์— getData()ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

extension CustomPickerButton {

    func getData() -> String? {
        if label.text == placeholder {
            return nil
        } else {
            return label.text
        }
    }
    
}

 

๋‹ค์Œ์œผ๋กœ

y(๋…„),m(์›”)์— ๋Œ€ํ•ด ๋งˆ์ง€๋ง‰ ๋‚ ์„ ์•Œ๋ ค์ฃผ๋Š” finishDayํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค!!

์˜ˆ๋ฅผ๋“ค์–ด finishDay(2023,1)์ด๋ฉด 31์ผ์„ returnํ•ด์ค๋‹ˆ๋‹ค.

finishDay๋Š” ์•„๋ž˜์˜ ๊ธ€์„ ์ฐธ๊ณ ํ•˜์—ฌ ๋งŒ๋“œ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค :)

https://990427.tistory.com/110

 

[Swift] Custom Calendar ๋‹ฌ์˜ ๋งˆ์ง€๋ง‰ ๋‚  ๊ตฌํ•˜๊ธฐ

์ด ๊ธ€์€ UI๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋‚ ์งœ ๊ณ„์‚ฐ์„ ํ•˜๋Š” ๋กœ์ง๋งŒ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค Custom Calendar๋ฅผ ๋งŒ๋“ค๋‹ค๋ณด๋‹ˆ ํ•ด๋‹นํ•˜๋Š” ๋‹ฌ์˜ ๋งˆ์ง€๋ง‰ ๋‚ ์ด ์–ธ์ œ์ธ์ง€ ๊ณ„์‚ฐํ•ด์•ผ ํ–ˆ๋‹ค. ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฒ˜๋Ÿผ ์ ‘๊ทผํ•˜๋ฉด ์œค ๋‹ฌ๋„ ๊ณ„์‚ฐํ•ด์ค˜์•ผ ํ•˜๊ณ 

990427.tistory.com

 

์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋งŒ๋“  daySetting()์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

getData()๋กœ ๋…„,์›”์„ ๊ฐ€์ ธ์˜ค๊ณ ~ finishDay()๋กœ ๋งˆ์ง€๋ง‰ ๋‚ ์„ ๊ตฌํ•˜๊ณ ~

dayPicker์— ๋ฐ์ดํ„ฐ ๋„ฃ์–ด์ฃผ๊ธฐ!

//CustomDatePicker.swift
func daySetting(){

    let y = yearPicker.getData()
    let m = monthPicker.getData()
    guard let yy = y, let mm = m else {
        dayPicker.setData(data: [])
        return
    }

    let last = finishDay(yy: yy, mm: mm)

    var days = [String]()
    for d in 1...last{
        days.append(String(d))
    }
    dayPicker.setData(data: days)
    dayPicker.isEnabled = true //์ผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ถ€๋ถ„!!
}

 

isEnabled

isEnabled๋Š” ๋ฒ„ํŠผ์˜ ์‚ฌ์šฉ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.

true๋ฉด ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๊ณ  false๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค!

 

๊ทธ๋ž˜์„œ ์ œ์ผ ์ฒ˜์Œ View๊ฐ€ setting๋˜๋Š” ์‹œ์ ์— (init, didAppear ์•„๋ฌด๋•Œ๋‚˜)

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์›”,์ผ์„ ์ œํ•œํ•ด์ฃผ์„ธ์š”!

์›”์€ ์ œํ•œํ•˜์ง€ ์•Š์•„๋„ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€๋Š” ์•Š์ง€๋งŒ ์ˆœ์ฐจ์ ์œผ๋กœ ์ž…๋ ฅํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์ œํ•œํ–ˆ์Šต๋‹ˆ๋‹ค.

monthPicker.isEnabled = false
dayPicker.isEnabled = false

 

 

์ž, ์ด์ œ CustomPickerButton์— ์žˆ๋Š” changed๋ฅผ ๊ด€์ฐฐํ•ด์„œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋ฐ˜์˜ ํ•ด์ฃผ์–ด์•ผ๊ฒ ์ฃ ?

๋จผ์ € ๋ฐ”์ธ๋”ฉ ํ•ด์ค๋‹ˆ๋‹ค.

์ด ํ•จ์ˆ˜๋Š” isEnabled์™€ ๊ฐ™์ด ์ดˆ๊ธฐํ™” ๋˜๋Š” ์‹œ์ ์— ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

//CustomDatePicker.swift
var disposeBag = DisposeBag()

func bind(){
    yearPicker.changed.subscribe { [unowned self] in
        self.yearCheck($0)
    }.disposed(by: disposeBag)

    monthPicker.changed.subscribe { [unowned self] in
        self.monthCheck($0)
    }.disposed(by: disposeBag)

}

 

๋จผ์ €, '๋…„'์ด ๋ฐ”๋€Œ๋ฉด ํ˜ธ์ถœ๋˜๋Š” yearCheck()ํ•จ์ˆ˜๋ฅผ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

//CustomDatePicker.swift
func yearCheck(_ year: String){
    if year != yearPicker.placeholder {
        monthPicker.isEnabled = true
        resetDay()
    }
}

 

(๋ชจ๋“  pickerButton์€ ์ˆซ์ž๋ฅผ ์„ ํƒํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ placeholder๋ฅผ ๋ฐฉ์ถœํ•ฉ๋‹ˆ๋‹ค)

'๋…„'์ด ์„ ํƒ๋˜์—ˆ์œผ๋ฉด, '์›”'์„ ํ™œ์„ฑํ™” ํ•˜๊ณ  day๋ฅผ resetํ•ด๋ผ

day๋ฅผ resetํ•˜๋Š” ์ด์œ ๋Š” ๋‚˜์ค‘์— '์ผ'์„ ์„ ํƒํ•œ ํ›„์—๋„ '๋…„'์„ ๋ฐ”๊ฟ€ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

resetDay()๋Š” day๋ฒ„ํŠผ์˜ ๊ฐ’์„ DD๋กœ ๋ฐ”๊พธ๊ณ , daySetting()์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

 

๋‹ค์Œ์€ '์›”'์ด ๋ฐ”๋€Œ๋ฉด ํ˜ธ์ถœ๋˜๋Š” monthCheck()์ž…๋‹ˆ๋‹ค.

func monthCheck(_ month: String){
    if month != monthPicker.placeholder {
        resetDay()
    }
}

 

์™„์„ฑํ•˜๋ฉด ์ด๋ ‡๊ฒŒ!!!

๋…„,์›”์ด ๋ณ€ํ™”ํ•จ์— ๋”ฐ๋ผ '์ผ'์ด ์ดˆ๊ธฐํ™” ๋ฉ๋‹ˆ๋‹ค

 

 

 

 

์ฝ”๋“œ ์ •๋ฆฌ

๋”๋ณด๊ธฐ

๋„ˆ๋ฌด ์ค‘๊ตฌ๋‚œ๋ฐฉ์ด๋ผ ์ˆ˜์ •๋œ ๋‚ด์šฉ์„ ๋ชจ์•„๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

public class CustomPickerButton: UIButton {
    var changed = PublishRelay<String>()
    
    func getData() -> String? {
        if label.text == placeholder {
            return nil
        } else {
            return label.text
        }
    }
    
    func setData(data: [String]){
        self.data = [""]+data
    }
    
    func resetData(){
        label.text = placeholder
    }   
}

extension CustomPickerButton : UIPickerViewDataSource, UIPickerViewDelegate {

    public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if data?[row] == "" {
            label.text = placeholder
        }
        else{
            label.text = data?[row]
        }
        changed.accept(label.text ?? placeholder)
    }

}

 

open class CustomDatePicker: UIView{

    func bind(){
        yearPicker.changed.subscribe { [unowned self] in
            self.yearCheck($0)
        }.disposed(by: disposeBag)

        monthPicker.changed.subscribe { [unowned self] in
            self.monthCheck($0)
        }.disposed(by: disposeBag)
    }
    
    func finishDay(yy: String, mm: String) -> Int{
        let formatter = DateFormatter()
        let calendar = Calendar(identifier: .gregorian)

        formatter.dateFormat = "yyyy-MM-dd"
        let st = formatter.date(from: "\(yy)-\(mm)-01")!
        let end = calendar.date(byAdding: .month, value: +1, to: st)!
        let result = calendar.dateComponents([.day], from: st, to: end)

        guard let day = result.day else {
            return 0
        }
        return day
    }
    
    func dataSetting(){
        var years = [String]()
        for y in 1970...dateFormatter("yyyy") {
            years.append(String(y))
        }
        yearPicker.setData(data: years.reversed())
        
        var months = [String]()
        for m in 1...12{
            months.append(String(m))
        }
        monthPicker.setData(data: months)
    }
    
    func daySetting(){
        
        let y = yearPicker.getData()
        let m = monthPicker.getData()
        guard let yy = y, let mm = m else {
            dayPicker.setData(data: [])
            return
        }
        
        let now_date = finishDay(yy: yy, mm: mm)
        
        var days = [String]()
        for d in 1...now_date{
            days.append(String(d))
        }
        dayPicker.setData(data: days)
        dayPicker.isEnabled = true
    }
    
    func yearCheck(_ year: String){
        if year != yearPicker.placeholder {
            monthPicker.isEnabled = true
            resetDay()
        }
    }
    
    func monthCheck(_ month: String){
        if month != monthPicker.placeholder {
            resetDay()
        }
    }
    
    func resetDay(){
        dayPicker.resetData()
        daySetting()
    }
}

 

 

ํœด ๋“œ๋””์–ด CustomDatePicker๋ฅผ ๋งŒ๋“ค์–ด ๋ƒˆ์Šต๋‹ˆ๋‹ค!

๊ทธ๋ž˜๋„ ์กฐ๊ธˆ ์•„์‰ฌ์šด ์ ์ด ์žˆ์–ด์„œ ๊ฐœ์„ ์„ ํ•ด์•ผํ• ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ใ…Žใ…Žใ…Žใ…Žใ…Ž

 

์–ธ์ œ๋“  ์ข‹์€ ์˜๊ฒฌ ์žˆ์œผ์‹œ๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š” ๐Ÿ˜ณ

 

 

 

 

 

 

์ €์ž‘์žํ‘œ์‹œ (์ƒˆ์ฐฝ์—ด๋ฆผ)

'๐Ÿ“ฑ iOS > UIKit' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

modalPresentationStyle ์„ค์ • ์‹œ์ (feat.ViewLifeCycle)  (0) 2024.06.14
[UIKit] TableView Multiple Cell, multi type json data parsing  (0) 2023.06.27
[UIKit] toast message ๋งŒ๋“ค๊ธฐ  (0) 2023.02.16
[UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (2/3)  (0) 2023.01.08
[UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (1/3)  (0) 2023.01.08
    '๐Ÿ“ฑ iOS/UIKit' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • modalPresentationStyle ์„ค์ • ์‹œ์ (feat.ViewLifeCycle)
    • [UIKit] TableView Multiple Cell, multi type json data parsing
    • [UIKit] toast message ๋งŒ๋“ค๊ธฐ
    • [UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (2/3)
    sladuf
    sladuf

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”