티스토리 뷰
728x90
Timers
타이머를 구현하려면 아래와 같은 방법이 있습니다.
- RunLoop
- Timer class
- DispatchQueue
RunLoop
NOTE
Apple 공식문서에서 RunLoop 클래스는 thread safe 하지 않아, 현재 thread에서만 RunLoop 메서드를 호출해야 한다고 합니다.
아래는 RunLoop를 활용해 1초마다 print를 하는 timer를 만든 예제 입니다.
import Foundation let runLoop = RunLoop.main let subscription = runLoop.schedule( after: runLoop.now, interval: .seconds(1), tolerance: .milliseconds(100)) { print("Timer fired") }
위 코드는 1초마다 "Timer fired" 가 프린트 되며,
아래처럼 Cancellable을 이용해 타이머를 취소시킬 수도 있습니다.import Foundation let runLoop = RunLoop.main let subscription = runLoop.schedule( after: runLoop.now, interval: .seconds(1), tolerance: .milliseconds(100)) { print("Timer fired") } // 추가 runLoop.schedule(after: .init(Date(timeIntervalSinceNow: 3.0))) { subscription.cancel() }
Timer
timer publisher는 아래와 같이 만들 수 있습니다.
let main = Timer.publish(every: 1.0, on: .main, in: .common)
두 가지 매개변수의 (on, in) 역할
On: 어떤 RunLoop에서 타이머를 사용할지, (위 예제에선 main thread)
In: 어떤 방식으로 타이머 Runloop를 실행할 건지, (여기선 기본값 common)
NOTE
Runloop의 동작방식을 모른다면 그냥 기본값을 사용하길 권장 합니다.
아래처럼 'on 파라미터'에 current를 사용해, 모든 thread에 대해 RunLoop를 얻을 수 있다는데..
안정성을 위해선 RunLoop.main을 사용하라는 말이 있음..let current = Timer.publish(every: 1.0, on: .current, in: .common)
필수!
타이머가 반환하는 Publisher는 ConnectablePublisher 인데, 이 Publisher를 구독하여 실행하려면 connect() 메서드를 호출해야합니다. 첫 subscriber가 구독할때, 자동으로 연결시켜주는 자매품 autoconnect() 메서드도 있어요!
따라서, 구독 시 타이머를 시작할 publisher를 만드는 방법은 아래처럼 작성하면 됩니다.
let publisher = Timer .publish(every: 1.0, on: .main, in: .common) .autoconnect()
아래 Timer는 현재 날짜를 반복적으로 방출하고, Publisher.Output 타입은 Date 입니다.
scan 연산자를 사용해 증가값을 내보내는 타이머를 만듭니다.let subscription = Timer .publish(every: 1.0, on: .main, in: .common) .autoconnect() // 이전 값에 +1을 함 (reduce는 최종값만 나타내지만, scan은 지속적으로 값을 보여줌) .scan(0) { counter, _ in counter + 1 } .sink { counter in print("Counter is \(counter)") } // Counter is 1 // Counter is 2 // Counter is 3 // Counter is 4 // .....
DispatchQueue
DispatchQueue를 사용하여 타이머를 생성할 수 있습니다.
아래는 DispatchQueue를 이용해 1초마다 이벤트를 방출하는 코드입니다.
1. 타이머 값을 보낼 Subject를 만듭니다.import Foundation import Combine let queue = DispatchQueue.main // 1 let source = PassthroughSubject<Int, Never>() // 2 var counter = 0 // 3 let cancellable = queue.schedule( after: queue.now, interval: .seconds(1) ) { source.send(counter) counter += 1 } // 4 let subscription = source.sink { print("Timer emitted \($0)") }
2. 타이머가 실행 될때마다 카운터를 증가시킵니다.
3. 1초마다 queue에 action을 (counter + 1, source에 counter 등록) 저장해놓습니다.
4. 타이머 값을 얻기 위해 subject를 구독합니다.
728x90
'iOS' 카테고리의 다른 글
[Combine] Chapter13 : Resource Management (0) | 2023.01.19 |
---|---|
[Combine] Chapter12 : Key-Value Observing (KVO) (0) | 2023.01.15 |
[Combine] Chapter10 : Debugging (0) | 2023.01.03 |
UIView vs CALayer (0) | 2022.12.28 |
[Combine] Chapter6 : Time Manipulation Operators (0) | 2022.11.24 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- Swift init
- RTCCameraVideoCapturer
- Swift ModernRIBs
- swift property
- Swift 알고리즘
- Swift 내림차순
- removeLast()
- Class
- swift reduce
- Swift Error Handling
- swift 고차함수
- ios
- swift (programmers)
- Swift 프로퍼티
- swift programmers
- Swift joined
- Swift 프로그래머스
- 2023년 회고
- Swift joined()
- Swift Leetcode
- Swift inout
- Combine: Asynchronous Programming with Swift
- RIBs tutorial
- CS 네트워크
- swift protocol
- Swift
- Swift final
- 원티드 프리온보딩
- iOS error
- Swift RIBs
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함