본문 바로가기
IOS/Swift

[Swift] UIProgressView와 AVAudioPlayer를 활용한 타이머 구현

by 얘리밍 2023. 3. 12.
320x100
728x90

 

Udemy 강의를 듣고 구현한 것을 정리..

 

 

 

 

1️⃣  카운트 다운을 위한 변수 생성 / UIProgressView 변수 생성

 

@IBOutlet weak var progressBar: UIProgressView!

...
var countdown = 60

 

 

 

 

2️⃣  타이머 객체 생성하기 / 오디오 객체 생성하기 

 

var timer = Timer()
var player = AVAudioPlayer();

 

 

 

 

3️⃣  버튼 클릭 시, 타이머 실행

 

 

guard !timer.isValid else {return} 은 타이머가 이미 실행중인 경우, 중복 실행을 방지하기 위해

해당 함수를 빠져나가도록 한다. 

 

초기 카운트 다운 변수를 해당 버튼에 맞는 타임으로 재설정해준다. 

 

@IBAction func hardnessSelected(_ sender: UIButton) {
        let hardness = sender.currentTitle!
        progressBar.progress = 0.0       // 프로그래스 바 진행 상황
        countdown = eggTimes[hardness]!  // 버튼 별 카운트 시간 
        
        
        
        guard !timer.isValid else { return }
                
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, 
        selector: #selector(timerAction), userInfo: nil, repeats: true)
        
    }

 

 

 

🔎 Timer.scheduledTimer 의 매개 변수들에 대해 더 자세히 알아보자 

 

  • timeInterval: 타이머 간격(초 단위)
  • target: 타이머가 실행될 객체(self)

  • selector: 타이머가 실행될 함수(#selector(실행함수이름))

  • userInfo: 타이머와 함께 전달할 추가 정보(nil)

  • repeats: 타이머 반복 여부(true/false)

 

 

 

 

4️⃣  타이머가 실행될 함수 구현

 

 

로직을 살펴보면 다음과 같다. 

 

timerAction() 

1) countdown 변수 값을 1씩 감소시킨다 

2) 0이 되면 타이머 종료 함수를 실행한다.

3) 진행 상황에 따른 비율로 프로그래스 바를 채운다. 

 

@objc func timerAction() {
		// 1. 시간에 따른 프로그래스 바 진행 상황 업데이트 
        progressBar.progress += 1/Float(countdown)
        
        // 2. 카운트다운 관련 
        if countdown > 0{
            print(countdown)
            countdown -= 1
        }else{
            stopTimer()
        }
    }

 

 

@objcObjective-C와의 상호 운용성을 위한 어노테이션이다. Objective-C에서는 메소드와 변수의 이름을 문자열로 전달하는 방식을 사용하기 때문에, Swift에서도 Objective-C와의 상호 운용성을 위해 @objc 어노테이션을 사용하여 Objective-C에서 호출 가능한 함수로 만들 수 있다. 

 

 

즉, @objc는 timerAction 함수를 Objective-C에서 호출 가능한 함수로 만들기 위해 사용됨

#selector 또한,  Objective-C와의 상호 운용성을 위한 문법으로, @objc 어노테이션을 사용한 함수를 선택할 수 있게 해줍니다.

 

 

 

 

 

5️⃣  타이머 종료 함수 구현( 종료 시, 종료 알림음 실행)

 

 

invalidate() 을 통해 타이머를 종료시키고, 프로그래스 바 값 또한 0으로 초기화 시킨다. 

 

func stopTimer() {
	// 1. 타이머 종료 
    timer.invalidate()  
    
    // 2. 종료 텍스트 띄우기 
    titleLabel.text = "Done!"
    
    // 3. 프로그래스 바 리셋 
    progressBar.progress = 0
	
    // 4. 오디오 실행 
    let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3")
    player = try! AVAudioPlayer(contentsOf: url!)
    player.play()
}

 

 

 

🔎 오디오 실행 코드를 더 자세히 알아보자

 

  1. Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3") 코드는 "alarm_sound.mp3"라는 파일이 앱 번들에 있는지 확인하고 그 파일의 경로(URL)를 반환한다. (Bundle.main은 현재 앱 번들을 의미)
  2. 반환된 URL을 AVAudioPlayer 객체의 contentsOf 메서드에 전달하여 player라는 이름의 AVAudioPlayer 객체를 생성함. 이때 try! 키워드는 오류가 발생하면 무시하도록 함. 

  3. player.play() 코드는 생성된 player 객체를 재생함. 

 

 

 

 

전체 코드 

더보기
import UIKit
import AVFoundation
class ViewController: UIViewController {
    
    @IBOutlet weak var progressBar: UIProgressView!
    @IBOutlet weak var titleLabel: UILabel!
    
    let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 7]
    var countdown = 60
    var timer = Timer()
    var player = AVAudioPlayer();
    
    override func viewDidLoad() {
            super.viewDidLoad()
        progressBar.progress = 0
        }
    
    
    @objc func timerAction() {
        progressBar.progress += 1/Float(countdown)
        if countdown > 0{
            print(countdown)
            countdown -= 1
        }else{
            stopTimer()
        }
        }

        func stopTimer() {
            timer.invalidate()
            titleLabel.text = "Done!"
            progressBar.progress = 0
            
            let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3")
            player = try! AVAudioPlayer(contentsOf: url!)
            player.play()
        }
    
    
    @IBAction func hardnessSelected(_ sender: UIButton) {
        let hardness = sender.currentTitle!
        countdown = eggTimes[hardness]!
        
        guard !timer.isValid else { return }
                
                timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
            }
        
        }

 

 

 

 

 

728x90
반응형