PomodoroTimer

jusong23·2022년 5월 11일
0

Swift

목록 보기
5/7
  • DataPicker를 통해 타이머 시간 설정 - 시간에 따른 특정작업 가능
  • 시작 일시정지 버튼으로 타이머 조절
  • 취소 버튼 누르면 종료
  • 카운트 다운이 완료되면 알람

📱Story Board

  • Asset에 pomodoro 사진 3개 추가
  1. image View 만들어 pomodoro 사진 넣기

  2. Label 00 : 00 : 00 만들어 중앙정렬

  3. Prograss View : 시간에 따른 작업경과를 나타냄 → progass 1로 해서 완전히 차게

  4. Data Picker가 Label과 Prograss를 덮도록 한다.

    → Prefered Style : Wheel , Mode : Count Down

  5. Label & Prograss Hidden 처리

  6. 취소 & 시작 버튼 Stack View → 취소버튼은 Enable false (시작했을 때 부터 보이게)

🧑‍💻Code

  1. Data Picker로 타이머 설정해놓고 시작버튼 누르면 Label & Progass만 뜨는 Code
override func viewDidLoad() {
        super.viewDidLoad()
        self.configureToggleButton()
    }

func configureToggleButton() {
        self.toggleButton.setTitle("시작", for: .normal)
        self.toggleButton.setTitle("일시정지", for: .selected)
    } // 버튼이 눌렸을때 버튼 설정이 바뀌게(viewDidLoad안에 작성)
  
func setTimerInfoViewVisble(isHidden: Bool) {
		    self.timerLabel.isHidden = isHidden
		    self.timerLabel.isHidden = isHidden
		} // 타이머 작동되면 isHidden 되도록 !
var duration = 60 // DataPicker 1분으로 초기화
var timerStatus: TimerStatus = .end
.
.
.
@IBAction func toggleButton(_ sender: Any) {
    self.duration = Int(self.dataPicker.countDownDuration) 
		// Data Picker에서 설정한 타이머 시간을 duration으로 초 표시 가능
    switch self.timerStatus {
    case .end: // 처음 기본 상태 (.end로 위에 초기화 되어있음)
				self.currentSeconds = self.duration
        self.timerStatus = .start
        setTimerInfoViewVisble(isHidden: false)
        self.dataPicker.isHidden = true
        self.toggleButton.isSelected = true
        self.cancleButton.isEnabled = true
				self.startTimer()
        
    case .start:
        self.timerStatus = .pasue
        self.toggleButton.isSelected = false 
				//"일시정지"로 띄워진 시작버튼(isSelected=true) 누르면 일시정지로 변경(isSelected=false)
        self.timer?.suspend()

    case .pasue:
        self.timerStatus = .start
        self.toggleButton.isSelected = true 
				// 다시 일시정지 버튼을 누르면 시작버튼 활성화
				self.timer?.resume()
        
    default:
        break
    } // 열거형에 따른 스위치문(같이 묶여서 쓰인다)
  }
}
  1. 버튼과 타이머를 연결하기(DispatchSourceTimer)
var timer: DispatchSourceTimer? 
// [GCB] Queue를 만들어 올리기만 하면 알아서 병렬적 작동(나중에)
    var currentSeconds = 0
.
.
func startTimer() {
    if self.timer == nil {
        self.timer = DispatchSource.makeTimerSource(flags: [], queue: .main)
 // [GCB] UI관련작업은 main Thread에서 !
        self.timer?.schedule(deadline: .now(), repeating: 1)
 // 타이머의 주기 설정 메소드
        self.timer?.setEventHandler(handler: { [weak self] in
            self?.currentSeconds -= 1
            debugPrint(self?.currentSeconds)

            if self?.currentSeconds ?? 0 <= 0 { 
// [조건문] self?.currentSeconds가 0보다 작거나 같다면 !
                self?.stopTimer()
            }
        })// 1초(repeating)에 한번씩 무슨일이 일어나게 할지를 핸들러 클로즈에 설정하기
        self.timer?.resume()
    }
} // Timer instance 작성해주기
func stopTimer() {
    debugPrint(timerStatus)
    if self.timerStatus == .end {
        self.timer?.resume()
    } // 일시정지 후 nil을 대입하려면, resume해야한다 (런타임 에러 방지)
    self.timerStatus = .end
    self.cancleButton.isEnabled = false
    self.setTimerInfoViewVisble(isHidden: true)
    self.dataPicker.isHidden = false
    self.toggleButton.isSelected = false
    self.timer?.cancel()
    self.timer = nil
    // 화면 벗어났을때도 타이머 종료되게 !
}
  1. Duration을 타이머 Label에 시/분/초로 표현, 그에맞게 Prograss 줄어듦 & 타이머 종료시 알람 울리기

    func startTimer() {
    .
    .
    guard let self = self else {return}
    self.currentSeconds -= 1
    let hour = self.currentSeconds / 3600
    let minutes = (self.currentSeconds % 3600) / 60
    let seconds = (self.currentSeconds % 3600) % 60
    self.timerLabel.text = String(format: "%02d:%02d:%02d", hour,minutes,seconds)
    self.prograssView.progress = Float(self.currentSeconds) / Float(self.duration)
    if self.currentSeconds ?? 0 <= 0 { 
    	// [조건문] self?.currentSeconds가 0보다 작거나 같다면 !
    	    self.stopTimer()
    	    AudioServicesPlaySystemSound(1005) 
    	// 완료 시 아이폰 기본 알람
  2. 🔥Prograss가 0에 가까워 질 수록 Data Picker 점점 사라지게 / 🔥Animation를 이용해 사라질때 스무스하게 사라지는 기능/ 🔥Pomodoro 계속 돌게 !

    • timerLabel & Prograss Hidden속성 제거 후 Alpha 값 0으로
    UIView.animate(withDuration: 0.5, animations: {
                self.timerLabel.alpha = 0
                self.prograssView.alpha = 0
                self.dataPicker.alpha = 1
            }) // 0.5초가 지나면 각자의 alpha 값은 0 -> 1 또는 1 -> 0 으로 바뀜
    .
    .
    .
    UIView.animate(withDuration: 0.5, animations: {
                self.timerLabel.alpha = 1
                self.prograssView.alpha = 1
                self.dataPicker.alpha = 0
            })
    • Pomodoro사진을 ImageView로 연결
    @IBOutlet weak var imageView: UIImageView!
    .
    .
    UIView.animate(withDuration: 0.5, delay: 0, animations: {
              self.imageView.transform = CGAffineTransform(rotationAngle: .pi)
          })
          UIView.animate(withDuration: 0.5, delay: 0.5, animations: {
              self.imageView.transform = CGAffineTransform(rotationAngle: .pi * 2)
          })  // animations parameter에 Closure 구현
    .
    **.
    .UIView.animate(withDuration: 0.5, animations: {
                self.timerLabel.alpha = 0
                self.prograssView.alpha = 0
                self.dataPicker.alpha = 1
                self.imageView.transform = .identity 
    						// 취소버튼 눌렸을 때 UIAnimation 종료
            }) // 0.5초가 지나면 각자의 alpha 값은 0 -> 1 또는 1 -> 0 으로 바뀜

0개의 댓글