2. Combine

김가영·2022년 8월 3일
0

concurrency

목록 보기
2/4
post-thumbnail
post-custom-banner

Combine이란?

combine은 asynchronous event를 처리하는 방법이다. (asynchrony는 앱의 main flow와 무관하게 진행되는 이벤트를 이야기한다.) 직접 thread를 조작하지는 않지만, 네트워크 요청 등의 concurrent한 이벤트들을 처리하는 데에도 이용된다.

combine은 이벤트로부터 파생되는 값들을 이용하는 방식을 통해 이벤트를 처리한다. 이러한 값들을 전달해주는 것들을 Publisher, 값들을 전달받는 것을 Subscriber라고 한다.

Publisher와 Subscriber

Publisher와 Subscriber는 프로토콜이다.

Publisher는 전달할 값의 타입을 정의한다. Publisher는 값을 하나만 전달할 수도 있지만, 여러개를 전달할 수도 있다. 예를 들어 URLSessiondataTaskPublisher(for:) 는 해당 네트워크 요청의 data task가 완료되면 data를 값으로 한 번 전달해주는 publisher를 리턴한다. 반면 Timer의 publish(every:tolerance:on:in:options:) 메서드가 리턴하는 publisher는 주어진 interval 마다 현재 날짜를 반복해서 전달해준다.

각Publisher는 추가로 이러한 값들을 조작할 수 있는 Operator들을 가지고 있다. operator는 Publisher를 리턴하는 메서드로, chaining 방식으로 상위 Publisher의 값들을 조작한 후 다시 값을 전달(republish)해준다.

Subscriber는 그 publisher chain의 가장 끝에서 값들을 전달받는 역할을 한다. 하지만 publisher는 subscriber가 연결되고, 값을 달라고 요청했을 때에만 값을 전달할 수 있다는 것을 기억하자.

간단하게 이용해보기

위에서 언급했듯이, Timer, URLSession, NotificationCenter 등 여러 Foundation Type들에서 이미 publisher를 제공하고 있다. 또한 자동으로 subscriber를 생성해서 publisher와 연결해주는 기본 메서드를 가지고 있기 때문에 publisher와 subscriber의 자세한 작동원리를 알지 못하더라도 이들을 간단하게 이용할 수 있다.

two built-in subscribers

  • sink(receiveCompletion:receiveValue:)receiveValue 를 통해 값을 전달받을 때마다 실행시킬 클로져를, receiveCompletion 을 통해 이벤트가 다 끝났을 때 실행시킬 클로져를 전달한다.
  • assign(to:on:) → keypath를 이용하여 값을 전달받을 때마다 object의 특정 property에 할당해준다.

NotificationCenter에서 기본으로 제공하는 publisher와 subscriber를 이용해보자. (자세한 예시는 Receiving and Handling Events With Combine을 참고)

NSControl.textDidChangeNotification은 text field 안의 텍스트가 변경될 때마다 object parameter로 text field를 저장해서 보내주는 notification이다.

해당 publisher는

위처럼 sink 메서드를 구현하고 있다. 이를 통해 위 publisher에서 전달해주고 있는 값은 Notification 타입임을 알 수 있다.

textDidChangeNotification은 notification의 object로 text field를 가지고 있기 때문에

위처럼 filterField라는 textField의 값이 바뀔때마다 그 텍스트를 출력하도록 combine을 이용할 수 있다.

추가로 Operator를 이용할 수도 있다. operator는 값을 조작한 후 기존의 publisher나 새로운 publisher를 리턴하는 방식을 통해 republish하는 역할을 한다.

여기에서는 map(_:) operator를 이용할 수 있는데, 기존에 array등의 collection에서 작동하는 방식과 유사하다.

위처럼 map operator는 상위 publisher로부터 값을 전달받아 새로운 값으로 리턴하면 그 값을 전달해주는 publisher를 생성해준다. 그 후 다시 sink()를 이용하면, 같은 역할을 하는 코드를 보다 직관적이게 표현 가능하다.

Reference

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

https://developer.apple.com/documentation/combine/receiving-and-handling-events-with-combine

More

Understanding Schedulers in Swift Combine Framework > https://www.vadimbulavin.com/understanding-schedulers-in-swift-combine-framework/

profile
개발블로그
post-custom-banner

0개의 댓글