[ Project ] ํผ์Šค๋„ ๋ชจ๋นŒ๋ฆฌํ‹ฐ์•ฑ #2 / Timer๋ฅผ ์ด์šฉํ•œ ์ด์šฉ ์‹œ๊ฐ„ ๊ตฌํ˜„

๐Ÿ“‘ Project โ”ƒ 2024. 4. 30. 01:21
๋ชฉ์ฐจ
  1. ์ดˆ๊ธฐ๊ตฌํ˜„๋ฐฉ๋ฒ•
  2. Timer
  3. Timer ์ƒ์„ฑ๋ฐฉ๋ฒ•
  4. Timer ์ ์šฉ
  5. ๊ตฌํ˜„ํ™”๋ฉด

 

์•ˆ๋…•ํ•˜์„ธ์š”~!

์˜ค๋Š˜์€ ํผ์Šค๋„ ๋ชจ๋นŒ๋ฆฌํ‹ฐ์•ฑ์—์„œ ํƒ€์ด๋จธ๋ฅผ ์ด์šฉํ•ด์„œ ์ด์šฉ์‹œ๊ฐ„์„ ๊ตฌํ˜„ํ•œ ๋ถ€๋ถ„์„ ๊ธฐ๋กํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค!โœจ

ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„ ์ค‘ ๊ธฐ๊ฐ„์ผ์„ ์ง€ํ‚ค๊ธฐ ์œ„ํ•ด ์ •์‹ ์—†์ด ๋‹ฌ๋ฆฌ๋‹ค ๋ณด๋‹ˆ ๊ธฐ๋ก์„ ๋งŽ์ด ๋ชปํ•œ ์ ์ด ์•„์‰ฌ์›Œ์„œ

์ด๋ฒˆ์ฃผ๋Š” ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„ ์ค‘์— ๊ณต๋ถ€ํ–ˆ๋˜ ๋‚ด์šฉ์„ ์œ„์ฃผ๋กœ ํฌ์ŠคํŒ…์„ ์ง„ํ–‰ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค~!

๋„ˆ๋ฌด๋„ˆ๋ฌด ๋ฐ”๋น ๋„ ๊ธฐ๋ก์€ ๊ผญ ์ฑ™๊ธฐ๊ธฐโญ๏ธ

 

 

 

์ดˆ๊ธฐ๊ตฌํ˜„๋ฐฉ๋ฒ•

ํ‚ฅ๋ณด๋“œ์˜ ๋Œ€์—ฌํ•˜๊ธฐ๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ, ํ‚ฅ๋ณด๋“œ์˜ ๋Œ€์—ฌ์‹œ๊ฐ„์„ ๋ณด์—ฌ์ฃผ๋„๋ก UI๋ฅผ ๊ตฌ์„ฑํ•˜์˜€์–ด์š”!

์ฒ˜์Œ์—๋Š” ๋Œ€์—ฌํ•œ ํ‚ฅ๋ณด๋“œ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ์— "๋Œ€์—ฌํ•˜๊ธฐ" ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ์˜ ์‹œ๊ฐ„์„ ์ €์žฅํ•ด ๋‘” ๋’ค ๊ทธ ์‹œ๊ฐ„๊ณผ ํ˜„์žฌ์˜ ์‹œ๊ฐ„์˜ ์ฐจ๋ฅผ ๊ตฌํ•˜์—ฌ ์ด์šฉ์‹œ๊ฐ„์ด ์ €์žฅํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์–ด์š”.

 


      
func calculateKickboardTotalTime() -> Int {
guard let start = getUserDefaultsKickboardStartTime().toDate() else {
return 0
}
return Int(Date().timeIntervalSince(start) / 60)
}

 

ํ•˜์ง€๋งŒ, ๋ฌธ์ œ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ ์šฉ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฌธ์ œ์˜€์Šต๋‹ˆ๋‹ค. View๋ฅผ ๋‹ค์‹œ ๊ทธ๋ฆด ๋•Œ๋Š” ์‹œ๊ฐ„์ด ์—…๋ฐ์ดํŠธ๋˜์–ด์„œ ์‹œ๊ฐ„์ด ๋‚˜ํƒ€๋‚˜์ง€๋งŒ, 1๋ถ„์ด ์ง€๋‚  ๋•Œ๋งˆ๋‹ค ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€ํ•˜๋Š” ์‹œ๊ฐ„์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ–ˆ์–ด์š”!

๊ทธ๋ž˜์„œ Timer๋ฅผ ์ ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

Timer

Timer๋Š” Foundation ํ”„๋ ˆ์ž„์›Œํฌ์— ์ •์˜๋˜์–ด ์žˆ๋Š” ๊ฐ์ฒด๋กœ ํŠน์ • ์‹œ๊ฐ„์„ ๊ฐ„๊ฒฉ์œผ๋กœ ์ฝ”๋“œ ๋ธ”๋ก์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋„๋ก ์˜ˆ์•ฝํ•˜๋Š”๋ฐ ์‚ฌ์šฉ์ด ๋ฉ๋‹ˆ๋‹ค. RunLoop์—์„œ ์ž‘๋™์„ ํ•˜๊ณ , ํŠน์ • ์‹œ๊ฐ„์— ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ์ง€์ •๋œ ๊ฐ€๊ฒฉ์œผ๋กœ ๋ฐ˜๋ณต ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

 

Timer ์ƒ์„ฑ๋ฐฉ๋ฒ•

scheduledTimer ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด Timer ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์–ด ํ˜„์žฌ ์•ฑ์˜ RunLoop์— ์ถ”๊ฐ€ํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


      
// ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•ด ํƒ€์ด๋จธ ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์‹คํ–‰๋  ๋•Œ, ์ฝ”๋“œ ๋ธ”๋ก์„ ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
func scheduledTimer(withTimeInterval: TimeInterval,
repeats: Bool,
block: (Timer) -> Void)
// objc selector๋ฅผ ์ด์šฉํ•ด ํƒ€์ด๋จธ ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์‹คํ–‰๋  ๋•Œ, ํ˜ธ์ถœํ•  ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •
// ๋˜ํ•œ userInfo๋ฅผ ํ†ตํ•ด ํƒ€์ด๋จธ ์‹คํ–‰ ์‹œ ํ•„์š”ํ•œ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๊ฐ€๋Šฅ
func scheduledTimer(timeInterval: TimeInterval,
target: Any,
selector: Selector,
userInfo: Any?,
repeats: Bool)
// NSInvocation ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด ํƒ€์ด๋จธ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ํ˜ธ์ถœ๋  ๋•Œ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •
func scheduledTimer(timeInterval: TimeInterval,
invocation: NSInvocation,
repeats: Bool)

 

์œ„์˜ ์„ธ ํ•จ์ˆ˜ ์ค‘ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜๋Š” ์ฒซ๋ฒˆ์งธ ํ•จ์ˆ˜๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค! ์„ธ ํ•จ์ˆ˜์˜ ๊ณตํ†ต์ ์ธ ๋ถ€๋ถ„์ด timeInterval๊ณผ repeats์ธ๋ฐ์š”!

  • timeInterval : ์ดˆ ๋‹จ์œ„๋กœ ํƒ€์ด๋จธ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ฃผ๊ธฐ
  • repeats : ๋ฐ˜๋ณต ์—ฌ๋ถ€
    • true - ํƒ€์ด๋จธ๊ฐ€ ๋ฐ˜๋ณต
    • false - ํƒ€์ด๋จธ ๋ฐ˜๋ณต๋˜์ง€ ์•Š์Œ.

 

์•„์ง ์„ธ๋ฒˆ์งธ ํ•จ์ˆ˜์˜ NSInvocation์— ๋Œ€ํ•œ ์ง€์‹์€ ์—†์–ด์„œ ๋‹ค์Œ์— ๊ณต๋ถ€ํ•ด ๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค~!

์ „ ์ฒซ๋ฒˆ์งธ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ํด๋กœ์ € ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํƒ€์ด๋จธ๊ฐ€ ๋ฐ˜๋ณต์ด ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋  ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

 

Timer ์ ์šฉ

 

์ฒซ ๋ฒˆ์งธ, ํƒ€์ด๋จธ๋ฅผ ๊ด€๋ฆฌํ•  ํด๋ž˜์Šค ํ˜•์„ฑ


      
import Foundation
class TimerManager {
static let shared = TimerManager()
private init() {}
}

์šฐ์„  Timer๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ TimerManager ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์—ˆ์–ด์š”!

static์œผ๋กœ ์„ ์–ธ๋œ share๋ผ๋Š” ๋ณ€์ˆ˜์— TimerManager์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ , ์ƒ์„ฑ์ž๋ฅผ private๋กœ ์„ ์–ธํ•จ์œผ๋กœ์จ ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋Š” shared ๋‹จ ํ•˜๋‚˜๋งŒ์„ ์„ ์–ธ๋˜๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

๋‘ ๋ฒˆ์งธ, ๋ณ€์ˆ˜์ƒ์„ฑ


      
var timer: Timer?
var elapsedTime: Int = 0

Timer์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ด์€ timer๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์‹คํ–‰์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ธฐ ์œ„ํ•œ elapsedTime์ด๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

์„ธ ๋ฒˆ์งธ, Timer ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ


      
func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
// ํƒ€์ด๋จธ๊ฐ€ 1์ดˆ ํ๋ฅผ ๋•Œ๋งˆ๋‹ค ์‹คํ–‰ํ•  ํ•จ์ˆ˜
}
}

์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋˜ ์„ธ๊ฐ€์ง€ ํ•จ์ˆ˜ ์ค‘ ์ฒซ ๋ฒˆ์งธ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Timer๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ RunLoop์— ์ถ”๊ฐ€ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. 1์ดˆ๋งˆ๋‹ค ๋ฐ˜๋ณต๋˜์–ด์„œ ์‹œ๊ฐ„์„ ์—…๋ฐ์ดํŠธํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด TimeInterval์„ 1๋กœ, repeats๋ฅผ true๋กœ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์–ด์š”~!

 

? ์—ฌ๊ธฐ์„œ [weak self]๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

Time ๊ฐ์ฒด๋Š” ํด๋กœ์ €๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ด ํด๋กœ์ €๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š”๋ฐ ํด๋กœ์ €๊ฐ€ self๋ฅผ strong์œผ๋กœ ์ฐธ์กฐํ•˜๊ฒŒ ๋˜๋ฉด, TimerManager์˜ ์ธ์Šคํ„ด์Šค์™€ Timer ์‚ฌ์ด์— ๊ฐ•ํ•œ ์ฐธ์กฐ ์‚ฌ์ดํด์ด ํ˜•์„ฑํ•˜๊ฒŒ ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”~!

 

 

 

๋„ค ๋ฒˆ์งธ, Timer๋ฅผ ์ค‘์ง€์‹œํ‚ฌ ํ•จ์ˆ˜ ์ƒ์„ฑ


      
func stopTimer() {
timer?.invalidate()
timer = nil
elapsedTime = 0
print("Timer stopped")
}

Timer๋Š” ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋„๋Š” ๊ฐ์ฒด์ด๋ฏ€๋กœ Timer๋ฅผ ์ค‘์ง€ํ•˜๋Š” ๋ถ€๋ถ„์ด ์•„์ฃผ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค~! Timer๋ฅผ ๋ฉˆ์ถ”์ง€ ์•Š์œผ๋ฉด ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์ ธ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‚ญ๋น„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์”ฉ ์ฝ”๋“œ๋ฅผ ๋œฏ์–ด์„œ ์„ค๋ช…ํ•˜์ž๋ฉด,

  • timer?.invalidate() : ํƒ€์ด๋จธ๊ฐ€ ๋ฏธ๋ž˜์— ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ์ค‘์ง€์‹œํ‚ค๊ณ , ํƒ€์ด๋จธ์˜ ์‹คํ–‰ ๋ฃจํ”„์—์„œ ์ œ๊ฑฐํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • timer = nil : ํƒ€์ด๋จธ๋ฅผ nil๋กœ ์„ค์ •ํ•จ์œผ๋กœ์จ TimerManager์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ Timer์— ๋Œ€ํ•œ ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.
  • elapsedTime : ํ˜„์žฌ ์‹คํ–‰ ์‹œ๊ฐ„์„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

์ž…๋‹ˆ๋‹ค.

 

 

๋‹ค์„ฏ ๋ฒˆ์งธ, ํƒ€์ด๋จธ๊ฐ€ 1์ดˆ ํ๋ฅผ ๋•Œ๋งˆ๋‹ค ์‹คํ–‰์‹œํ‚ฌ ํ•จ์ˆ˜ ์ƒ์„ฑ


      
private func timerDidFire() {
elapsedTime += 1
print("Timer updated: \(elapsedTime) seconds")
NotificationCenter.default.post(name: "timerUpdated", object: nil)
}

์šฐ์„  ํ˜„์žฌ ์‹คํ–‰์‹œ๊ฐ„์„ 1์ดˆ ์˜ฌ๋ฆฌ๊ณ ์š”!

NotificationCenter์˜ ์‹ฑ๊ธ€ํ†ค ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•ด postํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ด๋จธ๊ฐ€ 1์ดˆ ํ๋ฅผ ๋•Œ๋งˆ๋‹ค ์•Œ๋ฆผ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

์ด ํ•จ์ˆ˜๋ฅผ ์œ„์˜ startTimer์—์„œ ์‹คํ–‰์‹œ์ผœ ์ค๋‹ˆ๋‹ค!

 

 

์—ฌ๊ธฐ์„œ Notification์˜ ์ด๋ฆ„์„ ์ •ํ•˜๋Š”๋ฐ "timerUpdated"๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ธฐ๋„ ํ•˜๊ณ , ์˜คํƒ€๊ฐ€ ๋‚  ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ ๋”ฐ๋กœ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ƒ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”~!


      
extension Notification.Name {
static let timerUpdated = Notification.Name("timerUpdated")
}

 

 

 

์—ฌ์„ฏ ๋ฒˆ์งธ, ์†Œ๋ฉธ์ž ์ƒ์„ฑ


      
deinit {
stopTimer()
NotificationCenter.default.removeObserver(self)
}

์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋˜๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋˜๋Š” ์†Œ๋ฉธ์ž๋ฅผ ๊ตฌํ˜„ํ•ด ์ค๋‹ˆ๋‹ค!

ํƒ€์ด๋จธ ์ค‘์ง€์™€ notificationCenter์—์„œ ์˜ต์ €๋ฒ„๋ฅผ ์‚ญ์ œํ•ด ์ฃผ์–ด์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ํ•ด๊ฒฐํ•ด ์ค๋‹ˆ๋‹ค.

 

 

์ „์ฒดํ•จ์ˆ˜


      
//
// TimerManager.swift
// OneBoardProject
//
// Created by ๋ฐฐ์ง€ํ•ด on 4/28/24.
//
import Foundation
class TimerManager {
static let shared = TimerManager()
private init() {}
var timer: Timer?
var elapsedTime: Int = 0
func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
self?.timerDidFire()
}
}
func stopTimer() {
timer?.invalidate()
timer = nil
elapsedTime = 0
print("Timer stopped")
}
private func timerDidFire() {
elapsedTime += 1
print("Timer updated: \(elapsedTime) seconds")
NotificationCenter.default.post(name: .timerUpdated, object: nil)
}
deinit {
stopTimer()
NotificationCenter.default.removeObserver(self)
}
}
extension Notification.Name {
static let timerUpdated = Notification.Name("timerUpdated")
}

 

 

 

์ด์ œ ํƒ€์ด๋จธ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด ์คฌ์œผ๋‹ˆ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•ด์•ผ๊ฒ ์ฃ ?!

์ผ๊ณฑ ๋ฒˆ์งธ, 1์ดˆ๊ฐ€ ์ง€๋‚  ๋•Œ๋งˆ๋‹ค label ์—…๋ฐ์ดํŠธํ•˜๊ธฐ


      
// 1์ดˆ ์ง€๋‚ ๋•Œ๋งˆ๋‹ค ํƒ€์ด๋จธ ์—…๋ฐ์ดํŠธ
NotificationCenter.default.addObserver(self,
selector: #selector(handleTimerUpdate),
name: .timerUpdated,
object: nil)

NotificationCenter์˜ addObserver๋ฅผ ์‚ฌ์šฉํ•ด .timerUpdated๋ผ๋Š” ์ด๋ฆ„์˜ ์•Œ๋ฆผ์„ ๋ฐ›์„ ๋•Œ๋งˆ๋‹ค ์‹คํ–‰ํ•  ํ•จ์ˆ˜ handleTimerUpdate๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 


      
// 1์ดˆ๋งˆ๋‹ค label ์—…๋ฐ์ดํŠธ ์•ก์…˜
@objc func handleTimerUpdate() {
// UI ์—…๋ฐ์ดํŠธ๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰
DispatchQueue.main.async {
let time = TimerManager.shared.elapsedTime
self.rentalmodal.durationTimeNumberLabel.text = "\(time/60)๋ถ„ \(time%60)์ดˆ"
self.rentalmodal.totalPriceLabel.text = UserViewController().setPriceLabel(price: 500 + ( time / 60 ) * 180 )
}
}

UI ์—…๋ฐ์ดํŠธ๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— DispatchQueue.main.async๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ๊ณ , TimerManager์˜ ์‹ฑ๊ธ€ํ†ค ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ํ˜„์žฌ ์‹คํ–‰ ์‹œ๊ฐ„์ธ elpasedTime์˜ ๊ฐ’์„ ์ด์šฉํ•ด rentalmodal์˜ ๋ผ๋ฒจ์„ ์—…๋ฐ์ดํŠธํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

์ผ๊ณฑ ๋ฒˆ์งธ, startTimer()์™€ stopTimer() ์‹คํ–‰ํ•˜๊ธฐ

Timer๋Š” ๋Œ€์—ฌํ•˜๊ธฐ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์„ ๋•Œ, ํƒ€์ด๋จธ๊ฐ€ ์‹œ์ž‘ํ•˜๊ณ , ๋ฐ˜๋‚ฉํ•˜๊ธฐ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์„ ๋•Œ, ํƒ€์ด๋จธ๊ฐ€ ์ข…๋ฃŒ๋˜๋„๋ก ํ•˜์—ฌ ํ‚ฅ๋ณด๋“œ๋ฅผ ๋ ŒํŠธํ–ˆ์„ ๋•Œ๋งŒ์˜ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.


      
// MARK: - ํ‚ฅ๋ณด๋“œ ๋Œ€์—ฌ ๋ฒ„ํŠผ
@IBAction func rentButtonTapped(_ sender: UIButton) {
// ...
// ์ฝ”๋“œ ์ƒ๋žต
// ...
// ํƒ€์ด๋จธ ์‹œ์ž‘
TimerManager.shared.startTimer()
}

      
// MARK: - ํ‚ฅ๋ณด๋“œ ๋ฐ˜๋‚ฉ ๋ฒ„ํŠผ
@IBAction func returnBikeButtonTapped(_ sender: UIButton) {
if isSelectedAnnotation {
isSelectedAnnotation = false
// ...
// ์ฝ”๋“œ ์ƒ๋žต
// ...
// ํƒ€์ด๋จธ ์ข…๋ฃŒ
NotificationCenter.default.removeObserver(self)
TimerManager.shared.stopTimer()
}else {
returnAlertAction?()
print("์–ด๋…ธํ…Œ์ด์…˜์ด ์„ ํƒ๋˜์ง€ ์•Š์Œ")
}
}

 

 

๊ตฌํ˜„ํ™”๋ฉด

 

์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋ณ€๊ฒฝ๊ธˆ์ง€ (์ƒˆ์ฐฝ์—ด๋ฆผ)
  1. ์ดˆ๊ธฐ๊ตฌํ˜„๋ฐฉ๋ฒ•
  2. Timer
  3. Timer ์ƒ์„ฑ๋ฐฉ๋ฒ•
  4. Timer ์ ์šฉ
  5. ๊ตฌํ˜„ํ™”๋ฉด
'๐Ÿ“‘ Project' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [ Project ] ํผ์Šค๋„ ๋ชจ๋นŒ๋ฆฌํ‹ฐ์•ฑ #1 / ์ดˆ๊ธฐ ์™€์ด์–ด ํ”„๋ ˆ์ž„ / ๋งˆ์ดํŽ˜์ด์ง€ ๊ตฌํ˜„
  • [ Project ] WishListApp #7 / App Icon ๋ณ€๊ฒฝํ•˜๊ธฐ
  • [ Project ] WishListApp #6 / UIPageControl๊ณผ ScrollView๋ฅผ ์‚ฌ์šฉํ•œ ์ด๋ฏธ์ง€ ์Šค์™€์ดํ”„ ๊ตฌํ˜„ํ•˜๊ธฐ
  • [ Project ] WishListApp #5 / Pull to Refresh ์ ์šฉํ•˜๊ธฐ / UIRefreshControl
EarthSea
EarthSea
์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž ์งธ์ž…๋‹ˆ๋‹ค ๐ŸŒฑ
EarthSea's Log๐ŸŒ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž ์งธ์ž…๋‹ˆ๋‹ค ๐ŸŒฑ

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ๊ธ€์“ฐ๊ธฐ
EarthSea
EarthSea's Log๐ŸŒ
EarthSea

๊ณต์ง€์‚ฌํ•ญ

  • EarthSea's Introduce
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ
    • โœ๏ธ TIL
    • ๐Ÿ“‘ Project
    • ๐Ÿ“’ Study
      • ๐ŸŒ React
      • ๐Ÿšฉ Swift
      • ๐Ÿ“ UIKit
      • ๐Ÿ–ค Git
      • ๐Ÿฉต Python
    • ๐Ÿง‘๐Ÿปโ€๐Ÿ’ป Coding Test
      • โŒจ๏ธ Programmers
      • ๐Ÿ–Œ๏ธ BAEKJOON
    • ๐ŸŽ† SSAFY
    • ๐ŸŽ Apple
    • ๐Ÿท๏ธ Tistory
    • ์˜ค๋กฏ์ด ๋‚˜์˜ ์‹œ๊ฐ„
Total
Today
Yesterday
hELLO ยท Designed By ์ •์ƒ์šฐ.v4.2.2
EarthSea
[ Project ] ํผ์Šค๋„ ๋ชจ๋นŒ๋ฆฌํ‹ฐ์•ฑ #2 / Timer๋ฅผ ์ด์šฉํ•œ ์ด์šฉ ์‹œ๊ฐ„ ๊ตฌํ˜„
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”

๋‹จ์ถ•ํ‚ค

๋‚ด ๋ธ”๋กœ๊ทธ

๋‚ด ๋ธ”๋กœ๊ทธ - ๊ด€๋ฆฌ์ž ํ™ˆ ์ „ํ™˜
Q
Q
์ƒˆ ๊ธ€ ์“ฐ๊ธฐ
W
W

๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๊ธ€

๊ธ€ ์ˆ˜์ • (๊ถŒํ•œ ์žˆ๋Š” ๊ฒฝ์šฐ)
E
E
๋Œ“๊ธ€ ์˜์—ญ์œผ๋กœ ์ด๋™
C
C

๋ชจ๋“  ์˜์—ญ

์ด ํŽ˜์ด์ง€์˜ URL ๋ณต์‚ฌ
S
S
๋งจ ์œ„๋กœ ์ด๋™
T
T
ํ‹ฐ์Šคํ† ๋ฆฌ ํ™ˆ ์ด๋™
H
H
๋‹จ์ถ•ํ‚ค ์•ˆ๋‚ด
Shift + /
โ‡ง + /

* ๋‹จ์ถ•ํ‚ค๋Š” ํ•œ๊ธ€/์˜๋ฌธ ๋Œ€์†Œ๋ฌธ์ž๋กœ ์ด์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํ‹ฐ์Šคํ† ๋ฆฌ ๊ธฐ๋ณธ ๋„๋ฉ”์ธ์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.