[Udemy iOS & Swift Bootcamp] Egg Timer 만들기 (feat. Timer, UIProgressView)
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)
}
}
}