๐Ÿ“ฑ App Development Study/iOS๐ŸŽ

[Udemy iOS & Swift Bootcamp] Egg Timer ๋งŒ๋“ค๊ธฐ (feat. Timer, UIProgressView)

ibelieveinme 2023. 3. 25. 15:59
728x90

Udemy iOS & Swift Bootcamp 8๊ฐ• Egg Timer ๋งŒ๋“ค๊ธฐ์ด๋‹ค.

 

soft, medium, hard ๊ณ„๋ž€์„ ๋งŒ๋“œ๋Š”๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๊ณ , 1์ดˆ๊ฐ€ ํ๋ฅผ ๋•Œ๋งˆ๋‹ค progress bar์— ์ง„ํ–‰์ƒํ™ฉ์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ๋ฉ”์ธ ๊ธฐ๋Šฅ์ด๋‹ค. ์‹ค๋กœํฐ ์•ฑ ๋งŒ๋“ค๊ธฐ์—์„œ ๋ฐฐ์› ๋˜ ๋งˆ์ง€๋ง‰ ์ข…๋ฃŒ ํšจ๊ณผ์Œ๋„!

 

if/else๋ฌธ switch๋ฌธ, Dictionary, !? ํ‚ค์›Œ๋“œ, @objc ํ‚ค์›Œ๋“œ, Countdown Timer, UIProgressView ๋ฅผ ๋ฐฐ์› ๋‹ค.

๊ธฐ์–ตํ•˜๊ณ  ์‹ถ์€ ๋ถ€๋ถ„์€ Timer์ฝ”๋“œ์™€ UIProgressView์ด๋‹ค.


1. Timer ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

//Timer ๊ธฐ๋Šฅ ํ•ต์‹ฌ์ฝ”๋“œ

var countdownTimer: Timer!

countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)

 

Timer๋Š” ํƒ€์ด๋จธ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํด๋ž˜์Šค๋‹ค.

Timer.scheduledTimer์˜ ์ธ์ž๋ฅผ ์‚ดํŽด๋ณด์ž.

 

1) timeInterval: ์–ผ๋งˆ๋งŒํผ์˜ ์‹œ๊ฐ„๋งŒํผ Timer๋ฅผ ๋ฐ˜๋ณตํ•  ๊ฑด์ง€. ex) 1.0์ด๋ฉด 1์ดˆ์ด๊ณ  0์ด๋‚˜ ์Œ์ˆ˜๊ฐ’์„ ์ž…๋ ฅํ•˜๋ฉด 0.0001์ด default๋กœ ์‹คํ–‰๋œ๋‹ค.

2) target: selector์—๊ฒŒ ๋ณด๋‚ผ ๊ฐ์ฒด. self๋ฉด ๋‚ด ์ž์‹ ์„ ๋ณด๋‚ธ๋‹ค.

3) selector: timerInterval ๊ฒฝ๊ณผ๋งˆ๋‹ค target์„ ๋ณด๋‚ผ ํ•จ์ˆ˜๋ฅผ ์ž…๋ ฅํ•œ๋‹ค. ๋‚œ updateTime์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ฒฝ๊ณผ์‹œ๊ฐ„ ๋งˆ๋‹ค ํ•ด์•ผํ•  ์ผ์„ ์ ์–ด์ฃผ์—ˆ๋‹ค. 

4) userInfo: ํƒ€์ด๋จธ์˜ ์‚ฌ์šฉ์ž ์ •๋ณด๋ผ๋Š”๋ฐ ๊ทธ๋Ÿฐ๊ฑฐ ์—†์œผ๋‹ˆ๊นŒ nil ์ด๋ผ๊ณ  null๊ฐ’ ์ž…๋ ฅํ•ด์ฃผ๊ธฐ

5) repeats: Timer๋ฅผ timeInteval ๋งˆ๋‹ค ๋ฐ˜๋ณต์ˆ˜ํ–‰ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ ๋Š”๊ฒƒ. true ๋ฉด ๋ฐ˜๋ณต์‹คํ–‰, false๋ฉด ๋ฐ˜๋ณต์‹คํ–‰ ์•ˆํ•จ. ๋ฐ˜๋ณต์‹คํ–‰์‹œ, selector ํ•จ์ˆ˜์— ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•ด์ค˜์„œ ์ผ์ • ์กฐ๊ฑด์ด ๋˜๋ฉด Timer๋ฅผ ์ข…๋ฃŒํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค. 

 

//Timer ์ „์ฒด์ฝ”๋“œ

var countdownTimer: Timer!
var totalTime = 0
    
func startCountdown(timeValue: Int){
    countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}

//object C ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ํ•จ์ˆ˜๋ผ์„œ @objc ์ฃผ์„์ด ๋ถ™๋Š” ๊ฒƒ.
@objc func updateTime() {
    if totalTime >= 0 {
        totalTime -= 1
    }
    else {
        endTimer()
    }
}
    
func endTimer() {
    titleText.text = "Done!"
    playSound()

    countdownTimer?.invalidate()
    countdownTimer = nil
}

updateTime ์„ ๊ทธ๋ƒฅ func ํ‚ค์›Œ๋“œ๋งŒ ์“ฐ๋ฉด ์—๋Ÿฌ๊ฐ€๋‚œ๋‹ค. scheduledTimerํ•จ์ˆ˜๊ฐ€ Object-C์—์„œ ๋„˜์–ด์˜จ ์ฝ”๋“œ๋ผ์„œ ํ•จ์ˆ˜ ์•ž์— @objc ์ฐธ์กฐ ํ‚ค์›Œ๋“œ๋ฅผ ์ ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

์ž์„ธํ•œ ๋‚ด์šฉ์€ Apple Developer ๊ณต์‹๋ฌธ์„œ ์ฐธ๊ณ 

 

Timer | Apple Developer Documentation

A timer that fires after a certain time interval has elapsed, sending a specified message to a target object.

developer.apple.com

 

 

2. ProgressBar ๋งŒ๋“ค๊ธฐ

//ProgressBar ๊ธฐ๋Šฅ ํ•ต์‹ฌ์ฝ”๋“œ

@IBOutlet weak var progressBar: UIProgressView!

progressBar.progress = Float(passedSeconds) / Float(totalTime)

 

progress๊ฐ€ ์ง„ํ–‰๋ฐ”๋ผ์„œ ์ด ์ˆ˜์น˜๋ฅผ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋œ๋‹ค.

0~1 ์ด %๊ฐœ๋…์œผ๋กœ ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ์ด๋‹ค. 0.1 ~ 0.5 ~ 0.9 ~ 1 == 10% ~ 50% ~ 90% ~ 100% ์ด๋ ‡๊ฒŒ.

 

์ด ๋•Œ, ์ •์ˆ˜/์ •์ˆ˜ = ์ •์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ •์ˆ˜๊ฐ’์€ ๋‚˜๋ˆ„๊ธฐ ์ „์— ๋ฏธ๋ฆฌ ์‹ค์ˆ˜๋กœ ๋ฐ”๊ฟ”์„œ ๋‚˜๋ˆ ์ค˜์•ผ ํ•œ๋‹ค.

์•„๋‹ˆ๋ฉด 0์ด ๋‚˜์™€์„œ progress์— ์ ์šฉ์ด ์•ˆ๋œ๋‹ค.

 

//ProgressBar  ์ „์ฒด์ฝ”๋“œ

import UIKit
import AVFoundation


class ViewController: UIViewController {
    var SECONDS = 1
    var countdownTimer: Timer!
    let eggTime = [
        "Soft": 5, "Medium": 7, "Hard": 12
    ]
    var totalTime = 0
    var passedSeconds = 0

    @IBOutlet weak var titleText: UILabel!
    @IBOutlet weak var progressBar: UIProgressView!

    var player: AVAudioPlayer?


    @IBAction func onClickEgg(_ sender: UIButton) {
        if countdownTimer != nil { endTimer() }
        progressBar.progress = 0
        passedSeconds = 0

        let hardness = sender.currentTitle!
        titleText.text = "\(hardness) Start"

        startCountdown(timeValue: eggTime[hardness]!)
    }

    func startCountdown(timeValue: Int){
        totalTime = timeValue * SECONDS
        countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
    }
    
    //object C ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ํ•จ์ˆ˜๋ผ์„œ @objc ์ฃผ์„์ด ๋ถ™๋Š” ๊ฒƒ.
    @objc func updateTime() {
        if passedSeconds < totalTime {
            print("\(passedSeconds) seconds")
            passedSeconds += 1
            progressBar.progress = Float(passedSeconds) / Float(totalTime)
        }
        else {
            endTimer()
        }
    }

    func endTimer() {
        titleText.text = "Done!"
        playSound()

        countdownTimer?.invalidate()
        countdownTimer = nil
    }

    func playSound() {
        guard let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3") else { return }

        do {
            let player = try AVAudioPlayer(contentsOf: url)
            player.play()
        } catch let error {
            print(error.localizedDescription)
        }
    }
}

 

 


Timer, Progress ๊ธฐ๋Šฅ์„ ํฌํ•จํ•œ EggTimer ์™„์„ฑ ์•ฑ

 

[๋งŒ๋“  ์•ฑ์˜ Layout]

[์ „์ฒด์ฝ”๋“œ]

import UIKit
import AVFoundation

class ViewController: UIViewController {
    
    var SECONDS = 1
    var countdownTimer: Timer!
    let eggTime = [
        "Soft": 5, "Medium": 7, "Hard": 12
    ]
    var totalTime = 0
    var passedSeconds = 0

    @IBOutlet weak var titleText: UILabel!
    @IBOutlet weak var progressBar: UIProgressView!
    
    var player: AVAudioPlayer?

    
    @IBAction func onClickEgg(_ sender: UIButton) {
        if countdownTimer != nil { endTimer() }
        progressBar.progress = 0
        passedSeconds = 0
        
        let hardness = sender.currentTitle!
        titleText.text = "\(hardness) Start"
        
        startCountdown(timeValue: eggTime[hardness]!)
    }
    
    func startCountdown(timeValue: Int){
        totalTime = timeValue * SECONDS
        countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
    }
    
    //object C ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ํ•จ์ˆ˜๋ผ์„œ @objc ์ฃผ์„์ด ๋ถ™๋Š” ๊ฒƒ.
    @objc func updateTime() {
        if passedSeconds < totalTime {
            print("\(passedSeconds) seconds")
            passedSeconds += 1
            progressBar.progress = Float(passedSeconds) / Float(totalTime)
        }
        else {
            endTimer()
        }
    }
    
    func endTimer() {
        titleText.text = "Done!"
        playSound()
        
        countdownTimer?.invalidate()
        countdownTimer = nil
    }
    

    func playSound() {
        guard let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3") else { return }

        do {
            let player = try AVAudioPlayer(contentsOf: url)
            player.play()

        } catch let error {
            print(error.localizedDescription)
        }
    }
}
728x90