soultreemk 2022. 5. 8. 13:41

 

 

주요기능

1. DispatchSourceTimer : 반복적 주기로 특정 작업을 수행 (핸들러 호출)

 - Timer클래스 로도 구현 가능

 - GCD api내의 DispatchSourceTimer 메소드로 구현함

 

2. UIView Animation 

- view의 알파값을 조정하여 뷰가 사라지고 표시될때 자연스럽게 이동

- 이미지가 회전하도록 구현

 

 

 

//
//  ViewController.swift
//  pomodoro
//
//  Created by YANG on 2022/05/06.
//

import UIKit
import AudioToolbox

enum TimerStatus {
    case start
    case pause
    case end
}

class ViewController: UIViewController {

    @IBOutlet weak var datePicker: UIDatePicker!
    @IBOutlet weak var progressView: UIProgressView!
    @IBOutlet weak var timerLabel: UILabel!
    @IBOutlet weak var toggleBtn: UIButton!
    @IBOutlet weak var cancelBtn: UIButton!
    @IBOutlet weak var imageView: UIImageView!
    
    var duration = 60
    var timerStatus: TimerStatus = .end
    var timer: DispatchSourceTimer?
    var currentSeconds = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.configureToggleBtn()
        
    }
    
    func setTimerInfoViewVisible(isHidden: Bool) {
        self.timerLabel.isHidden = isHidden
        self.progressView.isHidden = isHidden
    }
    
    func configureToggleBtn() {
        self.toggleBtn.setTitle("시작", for: .normal)
        self.toggleBtn.setTitle("일시정지", for: .selected) // 버튼이 클릭되면 title 변경
    }
    
    func startTimer() {
        if self.timer == nil {
            self.timer = DispatchSource.makeTimerSource(flags: [], queue: .main)
            self.timer?.schedule(deadline: .now(), repeating: 1) // 1초마다 반복
            // 타이머가 동작할때마다 즉, 1초마다 handler내의 closure함수가 호출됨
            self.timer?.setEventHandler(handler: { [weak self] in
                guard let self = self else { return }
                self.currentSeconds -= 1
                let hour = self.currentSeconds / 3600
                let minute = (self.currentSeconds % 3600) / 60
                let seconds = (self.currentSeconds % 3600) % 60
                
                // 화면에 표시
                self.timerLabel.text = String(format: "%02d:%02d:%02d", hour, minute, seconds)
                self.progressView.progress = Float(self.currentSeconds) / Float(self.duration)
                
                // 이미지가 180도 변화
                UIView.animate(withDuration: 0.5, delay: 0, animations: {
                    self.imageView.transform = CGAffineTransform(rotationAngle: .pi)
                })
                // 180도 변화하는 애니메이션이 끝난 후 360도 회전
                UIView.animate(withDuration: 0.5, delay: 0.5, animations: {
                    self.imageView.transform = CGAffineTransform(rotationAngle: .pi * 2)
                })
                
                if self.currentSeconds <= 0 {
                    // 타이머가 종료
                    self.stopTimer()
                    AudioServicesPlaySystemSound(1005)
                }
            })
            self.timer?.resume()
        }
    }
    
    func stopTimer() {
        if self.timerStatus == .pause {
            self.timer?.resume()
        }
//        self.setTimerInfoViewVisible(isHidden: false)
//        self.datePicker.isHidden = true
        UIView.animate(withDuration: 0.5, animations: {
            self.timerLabel.alpha = 0
            self.progressView.alpha = 0
            self.datePicker.alpha = 1
            self.imageView.transform = .identity
        })
        
        self.toggleBtn.isSelected = false
        self.cancelBtn.isEnabled = false
        self.timer?.cancel()
        self.timer = nil
        
    }
    

    @IBAction func tabCancleBtn(_ sender: Any) {
        switch self.timerStatus {
        case .start, .pause:
            self.timerStatus = .end
            self.cancelBtn.isEnabled = false
            self.setTimerInfoViewVisible(isHidden: true)
            self.datePicker.isHidden = false
            self.toggleBtn.isSelected = false
        default:
            break
        }
    }
    
    @IBAction func tabToggleBtn(_ sender: Any) {
        self.duration = Int(self.datePicker.countDownDuration) // datePicker에서 설정한 시간을 초로 환산
        
        switch self.timerStatus {
        case .end:
            self.currentSeconds = self.duration
            self.timerStatus = .start
//            self.setTimerInfoViewVisible(isHidden: false)
//            self.datePicker.isHidden = true
            
            // closure에 최종값 설정: 현재값에서 원하는 최종값으로 변화
            UIView.animate(withDuration: 0.5, animations: {
                self.timerLabel.alpha = 1
                self.progressView.alpha = 1
                self.datePicker.alpha = 0
            })
            self.toggleBtn.isSelected = true
            self.cancelBtn.isEnabled = true
            self.startTimer()
            
        case .start:
            self.timerStatus = .pause
            self.toggleBtn.isSelected = false
            self.timer?.suspend()
            
        case .pause:
            self.timerStatus = .start
            self.toggleBtn.isSelected = true
            self.timer?.resume()
        }
        
    }
    
}