-
Ch5. Combining OperatorsRay Wenderlich/Combine 2021. 2. 12. 01:51
Prepending
prepend(Output...)
let publisher = [3, 4].publisher publisher .prepend(1, 2) .sink(receiveValue: { print($0) }) .store(in: &subscriptions)
1 2 3 4
prepend(Sequence)
Sequence프로토콜을 따르는 타입을 전달받을 수 있음
let publisher = [5, 6, 7].publisher publisher .prepend([3, 4]) .prepend(Set(1...2)) .prepend(stride(from: 6, to: 11, by: 2)) .sink(receiveValue: { print($0) }) .store(in: &subscriptions)
6 8 10 1 2 3 4 5 6 7
prepend(Publisher)
let publisher1 = [3, 4].publisher let publisher2 = PassthroughSubject<Int, Never>() publisher1 .prepend(publisher2) .sink(receiveValue: { print($0) }) .store(in: &subscriptions) publisher2.send(1) publisher2.send(2) publisher2.send(completion: .finished)
1 2 3 4
publisher2가 finish해야지 작동한다.
prepend할 publisher가 언제 끝날지도 모르는데 맘대로 prepend를 끝낼 순 없으니깐
Appending
append(Output...)
let publisher = PassthroughSubject<Int, Never>() publisher .append(3, 4) .append(5) .sink(receiveValue: { print($0) }) .store(in: &subscriptions) publisher.send(1) publisher.send(2) publisher.send(completion: .finished)
1 2 3 4 5
prepend와 반대로 여기는 첫번째 append할 지점을 정하기 위해서 publisher가 finish해야 한다.
append(Sequence)
let publisher = [1, 2, 3].publisher publisher .append([4, 5]) .append(Set([6, 7])) .append(stride(from: 8, to: 11, by: 2)) .sink(receiveValue: { print($0) }) .store(in: &subscriptions)
1 2 3 4 5 7 6 8 10
append(Publisher)
let publisher1 = [1, 2].publisher let publisher2 = [3, 4].publisher publisher1 .append(publisher2) .sink(receiveValue: { print($0) }) .store(in: &subscriptions)
1 2 3
switchToLatest
Publisher를 emit하는 Publisher가 등장한다.
let publisher1 = PassthroughSubject<Int, Never>() let publisher2 = PassthroughSubject<Int, Never>() let publisher3 = PassthroughSubject<Int, Never>() let publishers = PassthroughSubject<PassthroughSubject<Int, Never>, Never>() publishers .switchToLatest() .sink(receiveCompletion: { _ in print("Completed!") }, receiveValue: { print($0) }) .store(in: &subscriptions) publishers.send(publisher1) publisher1.send(1) publisher1.send(2) publishers.send(publisher2) publisher1.send(3) // 무시됨 publisher2.send(4) publisher2.send(5) publishers.send(publisher3) publisher2.send(6) // 무시됨 publisher3.send(7) publisher3.send(8) publisher3.send(9) publisher3.send(completion: .finished) publishers.send(completion: .finished)
1 2 4 5 7 8 9 Completed!
사용자가 버튼을 탭하면 네트워크를 요청을 생성하는 시나리오를 생각해보자.
사용자가 탭을 연타한다면??
let url = URL(string: "https://source.unsplash.com/random")! func getImage() -> AnyPublisher<UIImage?, Never> { URLSession.shared .dataTaskPublisher(for: url) .map { data, _ in UIImage(data: data) } .print("image") .replaceError(with: nil) .eraseToAnyPublisher() } let taps = PassthroughSubject<Void, Never>() taps .map { _ in getImage() } .switchToLatest() .sink(receiveValue: { _ in }) .store(in: &subscriptions) taps.send() DispatchQueue.main.asyncAfter(deadline: .now() + 3) { taps.send() } DispatchQueue.main.asyncAfter(deadline: .now() + 3.1) { taps.send() }
image: receive subscription: (DataTaskPublisher) image: request unlimited image: receive value: (Optional(<UIImage:0x600000364120 anonymous {1080, 720}>)) image: receive finished image: receive subscription: (DataTaskPublisher) image: request unlimited image: receive cancel image: receive subscription: (DataTaskPublisher) image: request unlimited image: receive value: (Optional(<UIImage:0x600000378d80 anonymous {1080, 1620}>)) image: receive finished
탭은 3번했지만, Fetch한 이미지는 2개뿐
merge(with:)
최대 8개까지만 머지가능
let publisher1 = PassthroughSubject<Int, Never>() let publisher2 = PassthroughSubject<Int, Never>() publisher1 .merge(with: publisher2) .sink(receiveCompletion: { _ in print("Completed") }, receiveValue: { print($0) }) .store(in: &subscriptions) publisher1.send(1) publisher1.send(2) publisher2.send(3) publisher1.send(4) publisher2.send(5) publisher1.send(completion: .finished) publisher2.send(completion: .finished)
1 2 3 4 5 Completed
combineLatest
최대 4개까지 combine가능
let publisher1 = PassthroughSubject<Int, Never>() let publisher2 = PassthroughSubject<String, Never>() publisher1 .combineLatest(publisher2) .sink(receiveCompletion: { _ in print("Completed") }, receiveValue: { print("P1: \($0), P2: \($1)") }) .store(in: &subscriptions) publisher1.send(1) publisher1.send(2) publisher2.send("a") publisher2.send("b") publisher1.send(3) publisher2.send("c") publisher1.send(completion: .finished) publisher2.send(completion: .finished)
P1: 2, P2: a P1: 2, P2: b P1: 3, P2: b P1: 3, P2: c Completed
zip
SwiftUI계의 만나게해듀오. 항상 짝을 만들어 드립니다.
let publisher1 = PassthroughSubject<Int, Never>() let publisher2 = PassthroughSubject<String, Never>() publisher1 .zip(publisher2) .sink(receiveCompletion: { _ in print("Completed") }, receiveValue: { print("P1: \($0), P2: \($1)") }) .store(in: &subscriptions) publisher1.send(1) publisher1.send(2) publisher2.send("a") publisher2.send("b") publisher1.send(3) publisher2.send("c") publisher2.send("d") publisher1.send(completion: .finished) publisher2.send(completion: .finished)
P1: 1, P2: a P1: 2, P2: b P1: 3, P2: c Completed
'Ray Wenderlich > Combine' 카테고리의 다른 글
Ch4. Filtering Operators (0) 2021.02.12 Ch3. Transforming Operators (0) 2021.01.27 Ch2. Publishers & Subscribers (0) 2021.01.27 Ch1. Hello, Combine! (0) 2021.01.27