티스토리 뷰
Timer 쓸 때, 편하게 썼던 autoconnect 는 ConnectablePublisher 의 메소드이다.
ConnectablePublisher 에 대해 자세히 알아보자.
[1] ConnectablePublisher
ConnectablePublisher 는 connection 을 명확히 지정할 수 있는 publisher 이다.
즉 connect 메소드를 직접 호출하기 전까지 값을 방출하지 않는다.
값이 방출되기 전에 추가적인 configuration 이나 setup 이 필요할 때,
구독자들이 다 준비된 후 이벤트를 방출하고 싶을 때
유용하다.
autoconnect 는 connection , disconnection 을 자동으로 해주는 메소드이다.
[2] ConnectablePublisher 만들기
failure type 이 Never 인 publisher 에 makeConnectable 을 호출해서 만들 수 있다.
let subject = PassthroughSubject<Int, Never>()
let connectablePublisher = subject.makeConnectable()
혹은 Publishers.MakeConnectable 의 이니셜라이저 로도 만들 수 있긴 하다.
let subject = PassthroughSubject<Int, Never>()
let connectablePublisher = Publishers.MakeConnectable(upstream: subject)
makeConnectable 쓰는게 더 일반적인 방법.
[3] 예제
import Combine
import Foundation
let subject = PassthroughSubject<Int, Never>()
// ConnectablePublisher로 변환
let connectablePublisher = subject.makeConnectable()
// 구독자 1 생성
let subscription1 = connectablePublisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
// 구독자 2 생성
let subscription2 = connectablePublisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
// ConnectablePublisher 연결
let connection = connectablePublisher.connect()
// 값 방출
subject.send(1)
// [출력]
// Subscription 1 received value: 1
// Subscription 2 received value: 1
// 연결 해제
connection.cancel()
// 더 이상 이벤트가 방출되지 않음
subject.send(2)
[4] Timer, Multicast
Timer.TimerPublisher, Publishers.Multicast 는 ConnectablePublisher 를 채택하고 있다.
그리고 share 는 편리하게 쓸 수 있는 Multicast (+PassthroughSubject), autoconnet 조합이다.
(아래에서 동작비교 할 것이기 때문에 리마인드!)
[5] 동작 비교 - 1 (정적 array)
# Publisher
let publisher = [1,2,3].publisher
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
// [출력]
// Subscription 1 received value: 1
// Subscription 1 received value: 2
// Subscription 1 received value: 3
// Subscription 2 received value: 1
// Subscription 2 received value: 2
// Subscription 2 received value: 3
# ConnectablePublisher
let publisher = [1,2,3].publisher.makeConnectable()
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
publisher.connect()
// [출력]
// Subscription 1 received value: 1
// Subscription 2 received value: 1
// Subscription 1 received value: 2
// Subscription 2 received value: 2
// Subscription 1 received value: 3
// Subscription 2 received value: 3
# Multicast
let publisher = [1,2,3].publisher.multicast {
PassthroughSubject()
}
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
publisher.connect()
// [출력]
// Subscription 1 received value: 1
// Subscription 2 received value: 1
// Subscription 1 received value: 2
// Subscription 2 received value: 2
// Subscription 1 received value: 3
// Subscription 2 received value: 3
# Share
(autoconnect 되기 때문에 타이밍 안맞음)
let publisher = [1,2,3].publisher.share()
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
// [출력]
// Subscription 1 received value: 1
// Subscription 1 received value: 2
// Subscription 1 received value: 3
[6] 동작 비교 - 2 (Timer)
# Timer > connect
let publisher = Timer.publish(every: 1, on: .main, in: .default)
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
publisher.connect()
// [출력]
// Subscription 1 received value: 2024-08-04 13:11:58 +0000
// Subscription 2 received value: 2024-08-04 13:11:58 +0000
// Subscription 1 received value: 2024-08-04 13:11:59 +0000
// Subscription 2 received value: 2024-08-04 13:11:59 +0000
...
# Timer > autoconnect
let publisher = Timer.publish(every: 1, on: .main, in: .default).autoconnect()
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
// [출력]
// Subscription 1 received value: 2024-08-04 13:13:10 +0000
// Subscription 2 received value: 2024-08-04 13:13:10 +0000
//
// Subscription 1 received value: 2024-08-04 13:13:11 +0000
// Subscription 2 received value: 2024-08-04 13:13:11 +0000
...
# Timer > share (이렇게 쓸 필요 없는 데 궁금하여..)
let publisher = Timer.publish(every: 1, on: .main, in: .default)
.share()
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
// 출력 안됨.
# Timer > 혹시 any publisher 로 erase 하면 ?
(그래도 ConnectablePublisher 의 특징이 유지됨.)
let publisher = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.eraseToAnyPublisher()
let subscription1 = publisher
.sink(receiveValue: { value in
print("Subscription 1 received value: \(value)")
})
let subscription2 = publisher
.sink(receiveValue: { value in
print("Subscription 2 received value: \(value)")
})
// [출력]
// Subscription 1 received value: 2024-08-04 13:17:02 +0000
// Subscription 2 received value: 2024-08-04 13:17:02 +0000
// Subscription 1 received value: 2024-08-04 13:17:03 +0000
// Subscription 2 received value: 2024-08-04 13:17:03 +0000
...
'🍏 > SwiftUI + Combine' 카테고리의 다른 글
[SwiftUI] Layout 을 이용한 SizeLogger (2) | 2024.08.12 |
---|---|
[SwiftUI] scrollClipDisabled (0) | 2024.08.12 |
[SwiftUI] Preferences (0) | 2024.05.23 |
[SwiftUI] animation(_:body:) 로 돌발애니메이션 막기 (1) | 2023.11.30 |
[SwiftUI] Drawing Curved Path with Animation (2) | 2023.10.29 |
- Total
- Today
- Yesterday
- Django FCM
- PencilKit
- Python Type Hint
- Django Heroku Scheduler
- Flutter Spacer
- cocoapod
- 장고 Custom Management Command
- SerializerMethodField
- flutter build mode
- Flutter Clipboard
- flutter deep link
- Sketch 누끼
- Django Firebase Cloud Messaging
- github actions
- 장고 URL querystring
- ribs
- Flutter 로딩
- 플러터 싱글톤
- Dart Factory
- METAL
- flutter dynamic link
- drf custom error
- Flutter Text Gradient
- Flutter getter setter
- ipad multitasking
- 플러터 얼럿
- DRF APIException
- Watch App for iOS App vs Watch App
- 구글 Geocoding API
- flutter 앱 출시
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |