Hello Combine
The Combine framework provides a declarative approach for how your app processes events. Rather than potentially implementing multiple delegate callbacks or completion handler closures, you can create a single processing chain for a given event source. Each part of the chain is a Combine operator that performs a distinct action on the elements received from the previous step.
→ 지정된 이벤트에 대한 단일 처리 체인을 만들 수 있다! 라는 것이 포인트인 것 같음
UIKit / AppKit 에서 발견할 수 있는 비동기 프로그래밍을 위한 도구
NotificationCenter / Delegate pattern / GCD & Operation / Closure
Combine basics
3가지 핵심 키워드 : Publishers, Operators, Subscribers
Publishers
Subscribers 에게 시간이 지남에 따라 하나 혹은 여려개의 이벤트를 전달
세가지 유형의 여러 이벤트를 보낼 수 있음
이벤트 종류는 어떤걸 의미하는지? → 모든 종류의 동적 데이터를 나타낼 수 있음
publisher 사용은 delegate 또는 completion callback 을 대신할 수 있다
추가적으로, 오류 처리 기능이 내장되어 있다.
Publisher 프로토콜은 2가지 타입이 존재한다.
Publisher.Output, Publisher.Failure
Operators
Publisher 프로토콜에 선언된 메서드
여러 연산자를 차례대로 호출하여 효과적으로 연결 가능하기에 매우 유용하다
Operator 메서드는 분리하거나 결합할 수 있다는 장점이 있다.
만약 Output이 다음 입력 유형과 일치하지 않다면 실행이 불가능하다
Operator를 통해 비동기적인 작업들의 순서를 정의할 수 있다
Operator는 일반적으로 upstream, downstream 이라고 하는 입출력이 항상 존재한다.
이를 통해 공유상태(shared state)를 피할 수 있다.
Subscribers (구독자)
Subscriber는 일반적으로 방출된 출력 또는 완료 이벤트를 이용하여 something을 수행한다.
현재, Combine은 데이터 스트림 작업을 간단하게 만들어주는 두개의 Subscribers를 제공한다.
sink subscriber : output values, completions 관련 클로저를 제공한다.
이를 통해 받은 이벤트로 원하는 것들을 처리할 수 있다.
assign subscriber : 사용자 지정 코드 없이 결과를 데이터 모델 또는 UI 컨트롤의 일부 속성에 바인딩할 수 있다. (화면에 직접 데이터를 표시할 수 있다.)
데이터에 대한 다른 요구사항이 있을 경우 custom subscriber 를 만드는 것이 publisher를 만드는 것보다 훨씬 쉽다.
Subscription (구독)
Subscription이 끝날때 Subscriber를 추가하면 체인 시작 부분에서 Publisher가 활성화 된다.
Publisher는 output을 받아줄 subscriber가 존재하지 않는다면 값을 방출하지 않는다.
Subscription은 비동기 이벤트 체인을 한번 선언한다면 다시 생각할 필요가 없는 훌륭한 개념을 갖고있다.
앱의 모든 부분에서 Combine을 사용한다면 앱의 전체 로직을 Subscription을 통해 설명할 수 있다.
Subscription은 데이터를 가져오는 작업 또는 호출할 작업을 하지않고 시스템이 모든 것을 실행할 수 있도록 해준다.
Subscription은 제스처, 타이머 종료와 같은 이벤트를 비동기적으로 실행할 수 있게 한다.
이런 과정에서 특히 좋은 점은 Combine에서 제공하는 Cancellable 프로토콜 덕분에 메모리 관리를 따로 하지 않아도 된다는 점이다.
Subscription code (the whole publisher, operators and subscriber call chain) 는 Cancellable 객체를 반환한다.
메모리에서 해당 객체를 해지할때마다 전체 subscription이 취소되고 메모리에서 해당 리소스가 해제된다. 이는 예를들어 VC에 subscription을 저장함으로써 subscription의 수명을 쉽게 binding 할 수 있는걸 의미한다.
이렇게 하면 사용자가 VC를 dismiss 할 때마다 속성이 deinitialize 되며 subscription 또한 취소될 수 있다.
또는 이 프로세스를 자동화하기 위해 유형에 [AnyCancellable] 컬렉션 속성을 갖고 원하는 만큼 그 안에 subscription을 추가할 수 있다. 속성이 메모리에서 해제된다면 모두 자동으로 취소되고 해제 된다.
What’s the benefit of Combine code over “standard” code?
Combine 사용 없이도 앱을 만들 수 있다. 하지만 Combine 프레임워크를 사용하는 것이
추상화 과정을 직접 구축하는 것보다 편리하고 안전하다.
Combine은 비동기 코드에 다른 추상화를 추가하는 것을 목표로 한다.
Key points
Combine은 비동기 이벤트를 처리하는 선언형, 리액티브 프레임워크이다.
Combine의 목적은 기존 문제를 해결하는 것이다. (예를들어 비동기 프로그래밍을 위한 tools 통합,
변하기 쉬운 상태 다루기, 오류 처리 해결)
Combine은 3가지 주요 타입을 통해 진행된다.
(시간이 지남에 따라 이벤트를 보내는 Pubishers, 업스트림 이벤트를 처리 및 조작하는 Operators,
결과를 소비하고 유용한 작업을 수행하는 Subscribers)
Publishers & Subscirbers
Publisher는 관심있는 이벤트를 publish 하거나 emit 할 수 있다.
publisher를 subscribing하는 개념은 NotificationCenter가 특정 notification을 subscribing 하는 개념과 유사하다.
NotificationCenter를 통해 특정 이벤트에 관심을 표시하고, 새 이벤트가 발생할 때마다 비동기식으로 알림을 받을 수 있다.
NotifcationCenter는 publisher(for:object:)라는 이름의 메소드를 갖고 있다.


기존 NotifcationCenter를 이용하여 비동기처리가 가능한데 publisher가 갖는 이점은 무엇일까? → publisher는 이전에 사용했던 비동기API를 새로운 대안과 연결해주는 다리 역할을 하게 된다
Pulbisher는 두가지 이벤트를 내보낸다. values, completion event.
Publisher는 values 값을 아예 보내지 않을 수도 혹은 1개 이상의 값을 내보낼 수도 있다. 하지만 completion event는 딱 한개만 내보낸다. completion event의 값은 정상값 혹은 에러값이다.
Publisher가 completion event를 내보낼때 publisher의 역할은 끝나고 더이상 이벤트를 내보내지 않게 된다.
Sink 오퍼레이터의 특징
Publisher가 제공해주는만큼 값을 전달받을 수 있다.
2가지 클로저를 제공해준다 → completion event, receive value
Just

Just는 Publisher 이다. 이벤트 결과를 각 Subscriber 에게 한번씩 전달하면 완료 상태가 된다.
Subscribing with assign(to:on:)
assing(to:on:) → KVO에 맞는 개체를 할당해준다.

UIKit의 경우 labels, text view, checkbox 등에 values를 전달하는 경우가 많은데 이때 유용하게 사용할 수 있다.
Republishing with assign(to:)

Publisher로 부터 받은 받은 값을 다시 Publish 하는 것이 republish.
@Published 속성을 사용하여 표현할 수 있음.

assign(to:on:) 대신 assign(to:) 을 사용하면 강한참조 문제를 해결할 수 있다.
Hello Cancellable
subscriber 가 작업을 마치고 더 이상 publisher로 부터 값을 받고 싶지 않다면 subscription을 취소하여 리소스를 확보하고 네트워크 호출과 같은 활동이 일어나지 않도록 하는 것이 좋다.
subscription에 대해 명시적으로 cancel() 메서드를 호출하지 않으면 publisher가 완료될 때까지
또는 저장된 subscription 이 deintialize 될 때까지 계속된다. 내가 직접 subscription을 취소할때 사라진다는 의미.
Understanding what’s going on

Creating a custom subscriber

Hello Future
Just 를 사용하여 subscriber에게 단일 값을 보내고 완료하는 publisher를 만들 수 있는 것과 마찬가지로
Future 를 사용하여 단일 결과를 비동기적으로 생성하여 완료할 수 있습니다.

Promise 타입은 클로저로서 Result 받거나 Error 를 받을 수 있습니다.
Result 는 Future 에 의해 publish 된 단일 값을 포함하고 있습니다.
Future는 greedy 하다! 생성되는 그 즉시 바로 실행된다.
일반적인 publisher 들은 subscriber를 필요로 한다 ← lazy 이기 때문에
Hello Subject
example(of: "PassthroughSubject") {
// 1
enum MyError: Error {
case test
}
// 2
final class StringSubscriber: Subscriber {
typealias Input = String
typealias Failure = MyError
func receive(subscription: Subscription) {
subscription.request(.max(2))
}
func receive(_ input: String) -> Subscribers.Demand {
print("Received value", input)
// 3
return input == "World" ? .max(1) : .none
}
func receive(completion: Subscribers.Completion<MyError>) {
print("Received completion", completion)
}
}
// 4
let subscriber = StringSubscriber()
}