Skip to content

Latest commit

Β 

History

History
125 lines (82 loc) Β· 3.77 KB

Chapter11_Timers.md

File metadata and controls

125 lines (82 loc) Β· 3.77 KB

Chapter 11: Timers

πŸ»β€β„οΈ Using RunLoop

  • Thread 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” 메인 μŠ€λ ˆλ“œμ™€ 직접 μƒμ„±ν•œ μŠ€λ ˆλ“œλŠ” RunLoop λ₯Ό κ°€μ§ˆ 수 μžˆλ‹€.
  • ν˜„μž¬ μŠ€λ ˆλ“œμ—μ„œ RunLoop.current λ₯Ό ν˜ΈμΆœν•˜λ©΄, Foundation 이 생성 ν•΄ 쀄 것이닀.

Note : RunLoop ν΄λž˜μŠ€λŠ” thread-safe ν•˜μ§€ μ•Šλ‹€. ν˜„μž¬ μŠ€λ ˆλ“œμ˜ run loop μ—μ„œλ§Œ RunLoop λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.


RunLoop λŠ” Scheduler ν”„λ‘œν† μ½œμ„ κ΅¬ν˜„ν•œλ‹€. low-level 에 κ΄€λ ¨λœ λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•˜κ³ , cancellable 타이머 생성할 수 μžˆλŠ” ν•˜λ‚˜κ°€ μžˆλ‹€.

let runLoop = RunLoop.main

let subscription = runLoop.schedule(
	after: runLoop.new, 
	interval: .seconds(1),
	tolerance: .milliseconds(100)
) {
	print("Timer fired")
}

νƒ€μ΄λ¨ΈλŠ” μ–΄λ–€ 값도 μ „λ‹¬ν•˜μ§€ μ•Šκ³  publisher λ₯Ό μƒμ„±ν•˜μ§€λ„ μ•ŠλŠ”λ‹€.


Combine κ³Ό κ΄€λ ¨ν•΄μ„œ, μœ μΌν•œ μœ μš©ν•œ 점은 Cancellable 을 톡해 μž μ‹œλ™μ•ˆ 타이머λ₯Ό 멈좜 수 있게 ν•΄μ€€λ‹€.

runLoop.schedule(after: .init(Date(timeIntervalSinceNow: 3.0))) {
	cancellable.cancel()
}

ν•˜μ§€λ§Œ RunLoop λŠ” 타이머λ₯Ό μƒμ„±ν•˜λŠ” 쒋은 방법이 μ•„λ‹ˆλ‹€. Timer 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ”κ²Œ 더 λ‚«λ‹€!


πŸ»β€β„οΈ Using the Timer class

Combine μ—μ„œλŠ” boilerplate 없이도 publisher 둜 λ°”λ‘œ μ‚¬μš© ν•  수 μžˆλ‹€.

let publisher = Timer.publish(every: 1.0, on: .main, in: .common)

RunLoop.current λ₯Ό ν˜ΈμΆœν•˜λ©΄ 직접 μƒμ„±ν–ˆκ±°λ‚˜ Foundation μ—μ„œ 얻은 μŠ€λ ˆλ“œμ—μ„œλ„ RunLoop λ₯Ό 얻을 수 μžˆλ‹€.

let publisher = Timer.publish(every: 1.0, on: .current, in: .common)

Note : 이 μ½”λ“œλ₯Ό DispatchQueue.main μ΄μ™Έμ˜ Dispatch queue μ—μ„œ μ‹€ν–‰ν•˜λ©΄ μ˜ˆμΈ‘ν•˜μ§€ λͺ»ν•œ κ²°κ³Όκ°€ λ°œμƒν•  수 μžˆλ‹€. Dispatch ν”„λ ˆμž„μ›Œν¬λŠ” run loop 을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  μŠ€λ ˆλ“œλ₯Ό κ΄€λ¦¬ν•œλ‹€. run loop 이 run λ©”μ†Œλ“œκ°€ ν”„λ‘œμ„ΈμŠ€ μ΄λ²€νŠΈμ—μ„œ 호좜되기λ₯Ό μš”κ΅¬ ν•˜κΈ° λ•Œλ¬Έμ—, main μ΄μ™Έμ˜ λ‹€λ₯Έ queue μ—μ„œ 타이머가 μ’…λ£Œλ˜λŠ” 것을 λ³Ό 수 없을 것이닀. μ•ˆμ „ν•˜κ²Œ RunLoop.main 은 νƒ€μ΄λ¨Έμ—κ²Œλ§Œ νƒ€κ²Ÿμ„ κ±Έμ–΄μ•Ό ν•œλ‹€.


ConnectablePublisher

  • 타이머가 λ¦¬ν„΄ν•˜λŠ” publisher
  • connect() λ©”μ†Œλ“œλ₯Ό 호좜 ν•˜κΈ° μ „κΉŒμ§€ subscription μ—μ„œ μ‹œμž‘ ν•˜μ§€ μ•ŠλŠ” Publishr λ³€μˆ˜
  • autoconnect() operator λ₯Ό μ‚¬μš©ν•΄μ„œ 처음 subscriber κ°€ ꡬ독 ν–ˆμ„ λ•Œ μžλ™μœΌλ‘œ μ—°κ²° ν•  수 μžˆλ‹€.
  • publisher λ₯Ό μƒμ„±ν•˜λŠ” κ°€μž₯ 쒋은 방법은 subscription μ‹œ 타이머λ₯Ό μ‹œμž‘ ν•˜λŠ”κ²ƒ
let publisher = Timer
	.publish(ever: 1.0, on: .main,  in: .common)
	.autoconnect()

이 νƒ€μ΄λ¨ΈλŠ” 반볡적으둜 ν˜„μž¬ λ‚ μ§œλ₯Ό emit , Publisher.Output νƒ€μž…μ€ Date

scan operator λ₯Ό μ‚¬μš©ν•΄μ„œ 타이머가 μ¦κ°€ν•˜λŠ” 값을 emit ν•˜κ²Œ ν•  수 μžˆλ‹€.

let subscription = Timer
	.publish(every: 1.0, on: .main,  in: .common)
	.autoconnect()
	.scan(0) { counter, _ in counter + 1 }
	.sink { counter in
		print("Counter is \(counter)")
}

πŸ»β€β„οΈ Using DispatchQueue

  • dispatch queue λ₯Ό μ‚¬μš©ν•΄ 타이머 이벀트λ₯Ό λ°œμƒμ‹œν‚€κΈ° μœ„ν•΄ 수 μžˆλ‹€.
let queue = DispatchQueue.main

let source = PassthroughSubject<Int, Never>()

var counter = 0

let cancellable = queue.scheule(
	after: queue.now,
	interval: .seconds(1)
) {
	source.send(counter)
	counter += 1
}

let subscription = source.sink {
	print("Timer emitted \($0)")
}

πŸ”‘ Key points

  • RunLoop 클래슀둜 타이머λ₯Ό 생성 ν•˜λŠ” 것은 Objective-C 의 였래된 방식이닀.
  • Timer.publish 둜 μ§€μ •λœ RunLoop μ—μ„œ μ§€μ •λœ κ°„κ²©λ§ˆλ‹€ 값을 μƒμ„±ν•˜λŠ” publisher λ₯Ό μ–»κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.
  • DispatchQueue.schedule λŠ” dispatch queue μ—μ„œ 이벀트λ₯Ό emit ν•˜λŠ” 타이머이닀.