Skip to main content

Command Palette

Search for a command to run...

Combine - Scheduler

Published
T

안녕하세요🙇🏻‍♂️ 세상을 더 편리하게 바꾸고 싶은 iOS 개발자 최인호입니다.

Hello 👋 I'm Inho Choi, an iOS developer who wants to change the world more conveniently.

  • 대학교 졸업
  • Apple Developer Academy @ POSTECH 1기
  • KWDC Main Organizer
  • AsyncSwift Organizer

Scheduler란 무엇인가?

Combine의 subscribe, cancel, 그리고 request operations. 을 어느 스레드에서 작동시킬지 결정하는 것을 말한다.

Combine의 기본 Scheduler

기본적으로 Publisher을 작동시킨 Thread에 따른다.

var publisher = PassthroughSubject<Int, Never>() 

publisher.sink {
    print(Thread.isMainThread)
}

DispatchQueue.main.async {
    publisher.send(400)
}
DispatchQueue.global().async {
    publisher.send(200)
}

정답은

true
false

가 나온다.

Scheduler란 무엇이 있는가?

Combine의 기본 Scheduler를 조정할 수 있는 함수가 2개가 있다.

  • receive(on:)

  • subscribe(on:)

아래의 예시를 다룰 것이다 기본적인 코드 위에서 제공된다.

struct IsMainThread: Publisher {
    typealias Output = String
    typealias Failure = Never

    func receive<S>(subscriber: S) where S : Subscriber, Never == S.Failure, String == S.Input {

        debugPrint("IsMainThread: \(Thread.isMainThread)")
        subscriber.receive(subscription: Subscriptions.empty)

        DispatchQueue.main.async {
            _ = subscriber.receive("test")
        }
    }
}

receive(on:)

하위 스트림의 Schedule을 결정해주는 함수

IsMainThread()
    .receive(on: RunLoop.main)
    .sink { _ in
        print("Sink: \(Thread.isMainThread)")
    }
    .store(in: &subscriptions)

// "IsMainThread: true"
// Sink: true

.receive(on: RunLoop.main) 로 인해서 Scheduler가 main으로 바뀌었다.

subscribe(on:)

IsMainThread()
    .subscribe(on: DispatchQueue.global())
    .sink { _ in
        print("Sink: \(Thread.isMainThread)")
    }
    .store(in: &subscriptions)
// "IsMainThread: false"
// Sink: true

.subscribe(on: DispatchQueue.global())에 의해서 subscribe의 upstream은 모두 DispatchQueue.global()위에서 작동한다.

그러므로 IsMianThread의 receive 함수는 global에서 작동하게 된다.

주의해야 할 점

Scheduler가 무엇이라고 정의했는가?

Combine의 subscribe, cancel, 그리고 request operations. 을 어느 스레드에서 작동시킬지 결정하는 것을 말한다.

subscribe cancle, request operation에만 Scheduler가 작동한다.

DispatchQueue.main.async {
    IsMainThread()
        .print("\(Thread.isMainThread)") // print Operator
        .subscribe(on: DispatchQueue.global())
        .sink {
            print("Sink: \(Thread.isMainThread)", $0)
        }
        .store(in: &subscriptions)
}
/* 1️⃣
"IsMainThread: false"
true: receive subscription: (Empty)
true: request unlimited
true: receive value: (test)
Sink: true test
*/

DispatchQueue.global().async {
    IsMainThread()
        .print("\(Thread.isMainThread)") // print Operator
        .subscribe(on: DispatchQueue.global())
        .sink {
            print("Sink: \(Thread.isMainThread)", $0)
        }
        .store(in: &subscriptions)
}
/* 2️⃣
"IsMainThread: false"
false: receive subscription: (Empty)
false: request unlimited
false: receive value: (test)
Sink: true test
*/

위 예시를 보자. print Operator는 어디서 작동할까?

1️⃣

Combine의 기본 Scheduler는 Publish 한 Thread가 된다.

main Thread에서 작동했고 subscribe에서 global로 바꿨다.

하지만 print Operator는 mainThread에서 작동했다고 뜬다.

이유는 뒤에서!

2️⃣

global Thread로 작동했고 subscribe를 통해서 global로 바꿔줬다.

print Operator는 global Thread에서 작동했다고 뜬다.

이유

Combine Scheduler는 subscribe, cancel, 그리고 request operations. 에서만 작동한다.

즉 Operator에 영향을 끼치지 않는다.

그러니 저 Publish에서 작동시켰는가에 따라서 작동한다.


참고한 사이트

https://developer.apple.com/documentation/combine

https://velog.io/@ictechgy/Combine-subscribeon-VS.-receiveon

https://trycombine.com/posts/subscribe-on-receive-on/

More from this blog

[CS] Https는 대칭키일까? 비대칭키일까?

결론: 둘 다 쓴다. 하지만 쓰는 타이밍은 다르다. 자세하기 알아보자. 혹시 모르니 용어는 정리해두자. 암호화 <-> 복호화 해독 = 복호화 비대칭키 해독은 대칭키 해독보다 오래 걸린다. 비대칭키를 쓰는 과정 💡 비대칭키는 대칭키를 만들기 위한 여정에 쓰인다. 뭔 소리지??? 대칭키를 만들기 위해서 비대칭키가 쓰인다고?? 비대칭키 해독은 대칭키 해독보다 오래걸린다. 1. Client가 Server에 접속을 요청하면 서버는 Secret ...

Jun 6, 202417

Xcode Cloud 사용 후기

애플에게 내는 친구비를 내며 Apple Developer 계정을 유지하려면 매년 애플에게 13만원의 친구비를 지불해야한다. 그리고 몇 개 친구 답례 상품을 주는데 그 중 하나가 Xcode Cloud 상품 주는데 안 쓸 이유는 없지 Xcode Cloud 개인에게는 과연? K-Spam 이라는 앱을 오랫동안 구상하고 드디어 출시를 했다. 생각보다 삽질을 많이 한 것 같다. 하지만 사이드 프로젝트의 진정한 의미는 삽질(?)하며 배우는 것이 아니겠나 개...

Jun 3, 202418

iOS Version 주의

앱 버전에는 상위버전이 출시한 상태에서 하위 버전을 아카이브 할 수 없음 예를 들어 출시한 버전이 1.3 이면 1.2로는 아카이브가 불가능함 단, 출시한 적이 없는 앱이라면 버전은 마음대로 지정 가능 App Store Connect의 버전 예를 들어 1.03 이랑 1.1 이랑 비교하면 앱 버전은 1.03 > 1.1 로 인식한다. . 단위로 잘라서 Int로 인식하는 것 같다. 그러니 0은 최대한 사용하지 않고 구분한다면 . 으로 구분해야겠다.

Jun 1, 20248

Toby의 iOS 블로그

34 posts

안녕하세요 세상을 더 편리하게 바꾸고 싶은 iOS 개발자입니다.