[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple/Combine & Rx

[Combine] timer (by Runloop, Timer Class, DispatchQueue)

inu 2022. 1. 13. 15:49
반응형

Combine을 통해 Timer를 생성하고 관리해보자.


Runloop

  • 입력소스 및 타이머 이벤트를 전달받는 인터페이스인 Runloop를 활용하여 Timer cacellable 객체를 생성할 수 있다.
  • Runloop 공식문서에서 cacellable 객체를 생성하는 메서드를 확인할 수 있다. (마지막 schedule 메서드)

Example

let runLoop = RunLoop.main

let subscription = runLoop.schedule(after: runLoop.now, interval: .seconds(2) , tolerance: .milliseconds(100)) {

    print("Timer fired")

}

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

Output

Timer fired
Timer fired

  • 현시간부터 2초마다 이벤트가 발생하는 Timer를 cacellable 형태로 생성하고 이를 3초뒤에 cancel하는 예제이다.
  • cf. tolerance: 허용오차범위

Timer Class

  • Timer class는 publisher를 생성하는 static 메서드를 제공한다.
  • 이를 통해 Timer.TimerPublisher를 생성한다.

  • 공식문서를 보면 이는 주어진 interval에 따라 현재의 date값을 방출하는 Publisher이다.
  • TimerPublisher는 ConnectablePublisher이기 때문에, 반드시 connect() 메서드로 연결을 해주어야 값을 생성해낸다. (https://developer.apple.com/documentation/combine/connectablepublisher)
  • autoconnect operator를 사용하면 connect() 과정없이 사용이 가능하다.

  • autoconnect operator는 connectable한 publisher의 연결과 비연결 과정을 자동화한다.
  • 이는 TimerPublisher같은 ConnectablePublisher의 작업을 단순화하기 위해 만들어졌다.
  • autoconnect는 하나의 Subscriber만 가질 경우 사용하는데, 이를 붙이면 subscriber의 구독과 동시에 connect() 메서드가 호출된다. 따라서 따로 connect() 메서드를 사용할 필요가 없어진다.

Example

let subscription = Timer.publish(every: 1.0, on: .main, in: .common)
                    .autoconnect()
    .sink {
        print($0)
}

Output

2022-01-13 06:30:06 +0000

2022-01-13 06:30:07 +0000

2022-01-13 06:30:08 +0000

2022-01-13 06:30:09 +0000

2022-01-13 06:30:10 +0000

2022-01-13 06:30:11 +0000

2022-01-13 06:30:12 +0000

2022-01-13 06:30:13 +0000

...

  • 1초가 지날 때마다 Date를 방출한다.

DispatchQueue

  • DispatchQueue는 Runloop와 사용방법이 유사하기 때문에 자세한 설명은 생략하겠다.

Example

let queue = DispatchQueue.main

let source = PassthroughSubject<Int, Never>()

var counter = 0

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

let subscription = source.sink {
    print($0)
}

Output

0
1
2
3
...

  • 1초가 지날 때마다 counter를 1씩 상승해 출력하는 예제이다.
반응형