-
DatePicker λ₯Ό ν΅ν΄ νμ΄λ¨Έ μκ°μ μ€μ ν μ μμ΅λλ€
-
μμ λ²νΌμ λλ₯΄λ©΄ νμ΄λ¨Έκ° μμλκ³ μΌμ μ μ§λ₯Ό λλ₯΄λ©΄ νμ΄λ¨Έκ° μΌμμ μ§ λ©λλ€
-
μ·¨μ λ²νΌμ λλ₯΄λ©΄ νμ΄λ¨Έκ° μ’ λ£λ©λλ€
-
μΉ΄μ΄νΈ λ€μ΄μ΄ μλ£λλ©΄ μλμ΄ μΈλ¦½λλ€
// in ViewController.swift
// timer λ₯Ό μ€μ νκ³ , timer κ° μμλλ method
func startTimer() {
// timer κ° nil μΌλ makeTimerSource μμ± : flags μ λΉλ°°μ΄ λκ²¨μ£Όκ³ , queue parameter μλ μ΄λ€ thread queue μμ λ°λ³΅λμν κ±΄μ§ μ€μ ν΄μ£Όλ κ²(timer κ° λλλ§λ€, UI μμ
μ ν΄μ€μΌ ν¨. μλ₯Ό λ€μ΄ λ¨μ μκ°μ νμν μ μκ² update ν΄μ€μΌ νλ©°, pregressView λ update ν΄μ€μΌ ν¨ => .main thread μμ λ°λ³΅ λμ νκ²λ μ€μ ν¨
// GCD μμ main thread λ app μ 체μμ μ€μ§ νκ°λ§ μ‘΄μ¬ν¨, κ·Έλμ μΌλ°μ μΈ code λ main thread μμ μ€νλλλ°, μμ±λ code λ cocoaμμ μ€νλλλ°, cocoa λ λ§€λ² main thread λ₯Ό νΈμΆν΄μ μμ
μ μ²λ¦¬νλ logic μ΄ μμ
// main thread μμ μ€μν μ μ, intefaced thread λΌκ³ λΆλ¦¬λλ°, user κ° interface μ μ κ·Όνλ©΄, event λ₯Ό main thread μ μ λ¬ λλ©°, μμ±ν code κ° κ±°κΈ°μ λ°μνκ² λ¨. μ¦, interface μ κ΄λ ¨λ code λ λ°λμ, main thread μμ μμ±λμ΄μΌ ν¨μ μλ―Έ ν©λλ€(UIμ κ΄λ ¨λ μμ
μ main thread μμ μ΄λ€μ ΈμΌν¨)
if self.timer == nil {
self.timer = DispatchSource.makeTimerSource(flags: [], queue: .main)
// schedule: μ΄λ ν μ£ΌκΈ°λ‘ timer κ° μ€νλλμ§ μ€μ ν΄μ€μΌ ν¨ deadline: .now λ timer κ° μμλλ©΄ μ¦μ μ€νλκ² ν¨ (μλ‘ 3μ΄λ€μ μ€νλμΌ νλ©΄ .now() + 3 ν΄μ£Όλ©΄ λ¨). repating μ λͺμ΄λ§λ€ λ°λ³΅ν κ±΄μ§ μ€μ νλκ² 1μ΄λ§λ€ λ°λ³΅ μ€μ
self.timer?.schedule(deadline: .now(), repeating: 1)
// setEventHandler: timer μ ν¨κ» μ°λλ eventHandler ν λΉ => ν΄λ‘μ Έ ν¨μλ‘ timer κ° λμν λ λ§λ€, handler closure ν¨μκ° νΈμΆμ΄ λ¨( μ¬κΈ°μ 1μ΄μ νλ²μ© handler μ ꡬνλλ code κ° μ€νλκ² λ¨)
self.timer?.setEventHandler(handler: { [weak self] in
// μΌμμ μΌλ‘ self κ° strong reference κ° λκ² ν¨
guard let self = self else { return }
self.currentSeconds -= 1 // μ΄λΉ 1μ© κ°μνκ² ν¨
// μ΄λ₯Ό μ,λΆ,μ΄λ‘ λ³ννκΈ°
let hour = self.currentSeconds / 3600 // μ΄λ₯Ό 3600 μΌλ‘ λλλ©΄ μκ°
let minutes = (self.currentSeconds % 3600) / 60 // λΆμ 3600μΌλ‘ λλ λλ¨Έμ§μμ 60 λλκΈ°
let seconds = (self.currentSeconds % 3600) % 60 // μ΄λ 3600μΌλ‘ λλ λλ¨Έμ§μ 60μ λλ¨Έμ§ κ°
// String ν¬λ©§ νμμΌλ‘ 2μ리 μ«μμ : μΌλ‘ ꡬλΆλ νμμΌλ‘ νκ³ , arguments μλ hour, minutes, seconds ν λΉ
self.timerLabel.text = String(format: "%02d:%02d:%02d", hour, minutes, seconds)
// debugPrint(self.currentSeconds)
// μκ°μ λ§μΆ°μ progressBar λ μ€μ΄λλ logic: countDown λκ³ μλ μκ°μ datePicker μμ μ€μ ν μ΄ μκ°μ λλ μ£Όλ©΄ countDown λ λλ§λ€ progress κ²μ΄μ§κ° μ€μ΄ λ€κ² λ¨(progress λ Float type μΌλ‘ λ³ν μμΌμΌ ν¨)
self.pregressView.progress = Float(self.currentSeconds) / Float(self.duration)
debugPrint(self.pregressView.progress)
// currentSeconds κ° 0λ³΄λ€ μκ±°λ, κ°λ€λ©΄ countDown μ΄ λλκ²μ΄κΈ° λλ¬Έμ
if self.currentSeconds <= 0 {
// timer μ’
λ£ code
self.stopTimer() // timer μ’
λ£
}
})
// hander closure κ° μλ£ λλ©΄ timer κ° μμλκ² ν¨
self.timer?.resume()
}
}
// timer κ° 0λ³΄λ€ κ°κ±°λ μμλ μ cancelBtn μ λλ₯΄λ©΄ timer κ° μ’
λ£λλ method
func stopTimer() {
// .pause μν μΌκ²½μ°μ resume method μμ±λκ² μμ±
if self.timerStatus == .pause {
self.timer?.resume()
}
self.timerStatus = .end
self.cancelBtn.isEnabled = false
self.setTimerInfoViewVisable(isHidden: true)
self.datePicker.isHidden = false
self.toggleBtn.isSelected = false
self.timer?.cancel() // timer μ’
λ£
self.timer = nil // timer λ©λͺ¨λ¦¬μμ ν΄μ¬ μν΄: ν΄μ¬ μμν€λ©΄ νλ©΄μ λ²μ΄λλ, timer κ° κ³μ λμ ν μ μμ
}
iPhone AudioServices - https://iphonedev.wiki/index.php/AudioServices
import AudioToolbox
if self.currentSeconds <= 0 {
// timer μ’
λ£ code
self.stopTimer() // timer μ’
λ£
// 0μ΄ λλ©΄ μλ¦Ό μΈλ¦¬κ² ν¨: μμ΄ν° κΈ°λ³Έ alert μ¬μ΄λ μ¬μ μν΄
AudioServicesPlaySystemSound(1005)
}
})
// hander closure κ° μλ£ λλ©΄ timer κ° μμλκ² ν¨
self.timer?.resume()
}
- Viewμ μ¬λΆλ₯Ό isHidden κ°μ΄ μλ, alpha κ°μΌλ‘ μ€μ ν΄μ View κ° μ¬λΌμ§κ³ νμλκ² λ§λλλ€. alpha κ°μ opacity κ°μ μ‘°μ νλ μΈμ μ λλ€. μ΅μ 0 ~ 1κΉμ§ μ€μ νλλ° 0 μ κ°κΉμΈμλ‘ view κ° ν¬λͺ ν΄ μ§λλ€.
func stopTimer() {
// .pause μν μΌκ²½μ°μ resume method μμ±λκ² μμ±
if self.timerStatus == .pause {
self.timer?.resume()
}
self.timerStatus = .end
self.cancelBtn.isEnabled = false
// alpha κ° μ‘°μ μ ν΅ν animation
UIView.animate(withDuration: 0.5, animations: {
self.timerLabel.alpha = 0
self.pregressView.alpha = 0
self.datePicker.alpha = 1
})
@IBAction func tabCancelBtn(_ sender: UIButton) {
switch self.timerStatus {
// start, paue μνμμ cancelBtn λλ₯΄λ©΄ .end μνλ‘ λκ³ , cancelBtn μ λΉνμ±νλ‘ νκ³ , timerLabelκ³Ό pregressView κ° νμλμ§ μκ²ν¨, datePicker κ° λ€μ νμλκ² ν¨, toggleBtnμ΄ strart λκ² ν¨
case .start, .pause:
switch self.timerStatus {
// end μΌκ²½μ° μμ§ μμ μνμν timer label κ³Ό progressView κ° νμλκ² νκ³ , datePicker κ° hidden λκ² ν¨
case .end:
self.currentSeconds = self.duration // νμ¬ μκ°μ duration μ λμ
μν΄
self.timerStatus = .start
// alpha κ° μ‘°μ μ ν΅ν animation
UIView.animate(withDuration: 0.5, animations: {
self.timerLabel.alpha = 1
self.pregressView.alpha = 1
self.datePicker.alpha = 0
})
// image rotation animation
UIView.animate(withDuration: 0.5, delay: 0, animations: {
// CGAffineTransform μ ꡬ쑰체 μΈλ°, view μ frame μ κ³μ°νμ§ μκ³ 2D κ·Έλν½μ 그릴 μ μμ΅λλ€. (μλ₯Ό λ€μ΄ Viewλ₯Ό μ΄λ μν€κ±°λ, νμ μν€λ ν¨κ³Όλ₯Ό μ€μ μμ΅λλ€. rotationAngle: .pi μ 180λ νμ μ μλ―Έν©λλ€.
self.imageView.transform = CGAffineTransform(rotationAngle: .pi)
})
// λ€μ 360λ νμ μν΄ : μμ 180 λ νμ animation μ΄ λλλ©΄ λμ ν μ μκ² delay 0.5 μ€μ
UIView.animate(withDuration: 0.5, delay: 0.5, animations: {
self.imageView.transform = CGAffineTransform(rotationAngle: .pi * 2)
})
self.imageView.transform = .identity // cancel λλ©΄ imageView κ° μμνλ‘ λκ² ν¨
Describing check point in details in Jacob's DevLog - https://jacobko.info/ios/ios-06/
-
Timer λ₯Ό suspend λ₯Ό μ¬μ©ν΄μ μΌμμ μ§ νκ² λλ©΄, μμ§ μνν΄μΌ λ μμ μ΄ μμμ μλ―ΈνκΈ° λλ¬Έμ, suspend λ timer μ
nil
μ λμ νκ² λλ©΄runTime error
λ°μ λ¨ -
μΌμμ μ§ λ μνμμ timer λ₯Ό μ€μ§νκ³ , nil μ λμ νλ €λ©΄ κ·Έμ μ resume method λ₯Ό μ€ν μμΌμΌ ν¨
// in ViewController.swift
// timer κ° 0λ³΄λ€ κ°κ±°λ μμλ μ cancelBtn μ λλ₯΄λ©΄ timer κ° μ’
λ£λλ method
func stopTimer() {
// .pause μν μΌκ²½μ°μ resume method μμ±λκ² μμ±
if self.timerStatus == .pause {
self.timer?.resume()
}
self.timerStatus = .end
self.cancelBtn.isEnabled = false
self.setTimerInfoViewVisable(isHidden: true)
self.datePicker.isHidden = false
self.toggleBtn.isSelected = false
self.timer?.cancel() // timer μ’
λ£
self.timer = nil // timer λ©λͺ¨λ¦¬μμ ν΄μ¬ μν΄: ν΄μ¬ μμν€λ©΄ νλ©΄μ λ²μ΄λλ, timer κ° κ³μ λμ ν μ μμ
}
πΆ π· π π π
Jacob's DevLog - https://jacobko.info/ios/ios-07/
μ¬:νΈμ§ κ°λ°λΈλ‘κ·Έ - https://dev-dream-world.tistory.com/133
fastcampus - https://fastcampus.co.kr/dev_online_iosappfinal