아요 개발 일기

[Combine] - Subject 본문

iOS/Combine

[Combine] - Subject

소진이 2023. 1. 16. 09:25

안녕하세요~ 소진입니다!

이번에는 Subject에대해 알아보겠습니다!

 

Publisher와 Subscriber에 대해 모른다면 아래 글을 참고하세요!

 

https://develop-ssooo.tistory.com/89

 

[Combine] - Publisher, Subscriber

안녕하세요 소진입니다! 요즘 SwiftUI를 계속해서 공부하고있는데, Combine은 무조건무조건 필수로 알아야겠더라구요! RxSwift하느라 이제야 제대로 살펴보네요.. 대충 사용은 해봤는데 정확히 알고

develop-ssooo.tistory.com

 


자,

바로 공식문서 보러갑시다!

 

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

 


Subject는 외부 호출자(outside callers)가 element를 publish 할 수 있는 방법을 제공하는 publisher


 

외부에서 element를 publish할 수 있는 방법을 제공하는 publisher....이라...

.... 결국은 publisher라는 말인가..

 

 

Subject는 Publisher 프로토콜을 채택하고 있고

 아래와 같이 2가지의 conforming type을 가지고 있습니다

 

CurrentValueSubject

PassthroughSubject

 

자세히 알아보겠습니다:)

 


 

CurrentValueSubject

 

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

 

 


single value을 래핑하고 값이 변경될 때마다 새 element를 publish하는 subject입니다.

 

PassthroughSubject와 달리 CurrentValueSubject는 가장 최근에 publish된 element의 buffer를 유지합니다.

CurrentValueSubject에서 send(_:)를 호출하면,

현재 값도 업데이트되므로 값을 직접 업데이트하는 것과 같습니다.


 

간단히

 

CurrentValueSubject는 초기 값이 필요하고

가장 최근에 받은 값을 들고 있습니다

 

로 정리해보았습니다!

 

 

코드로 살펴봅시다 ㅎㅎ

let variable = CurrentValueSubject<String, Never>("")

variable.send("Initial text")

let subscription3 =  variable.sink (receiveCompletion: { (result) in
    switch result {
    case .finished:
        print("finished")
    case .failure(let error):
        print(error.localizedDescription)
    }
}, receiveValue: { value in
    print("CurrentValueSubject 데이터: \(value)")
})

let publisher = ["Here", "we", "go"].publisher
publisher.subscribe(variable)

[출력]
CurrentValueSubject 데이터: Initial text
CurrentValueSubject 데이터: Here
CurrentValueSubject 데이터: we
CurrentValueSubject 데이터: go
finished

 

 

PassthroughSubject

 

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

 


downstream subscribers에게 element를 broadcasts하는 subject입니다.

 

Subject의 구체적인 구현으로, 

그 PassthroughSubject는 기존 명령형 코드를 Combine 모델에 적용하는 편리한 방법을 제공합니다.

 

CurrentValueSubject와 달리 PassthroughSubject에는 가장 최근에 publish element의 초기 값이나 buffer가 없습니다.

PassthroughSubject는 subscribers가 없거나 현재 수요(demand)가 0인 경우 value를 삭제(drop)합니다.


간단히

 

PassthroughSubject는 초기 값이 필요 없고,

받은 값을 전달해주기만 하며, 전달한 값을 들고 있지 않습니다

 

인 것 같습니다!

 

 

예시코드 같이 살펴봅시다

 

let relay = PassthroughSubject<String, Never>()

let subscription1 = relay.sink { value in
    print("PassthroughSubject value: \(value)")
}

relay.send("Hello")
relay.send("Sojin")

[출력]
PassthroughSubject value: Hello
PassthroughSubject value: Sojin

 

아우 쉬워라~~

근데 새로운 send라는게 있네요??

send는 데이터를 보낼때 사용합니다!!

send에는 아래와 같이 3가지 유형이 있는데요!

 

 

input은 그냥 원하는 값을 넣으면 되구요!

completion은 completion signal을 보내는 메소드입니다

 

 

finished와 failure() 두가지가 있습니다

코드로 같이 살펴 봅시다!

 

let relay = PassthroughSubject<String, Error>()

 

우선 위처럼 Never을 Error로 변경해주어야합니다!

failure로 오류처리 하려면 Never이 아니라 Error로 적어줘야 동작하거든요 ㅎㅎ

 

enum SojinError: Error {
    case unknown
}

let subscription3 =  relay.sink (receiveCompletion: { (result) in
    switch result {
    case .finished:
        print("finished")
    case .failure(let error):
        print("에러 삐용삐용")
        print(error.localizedDescription)
    }
}, receiveValue: { value in
    print("PassthroughSubject 데이터: \(value)")
})

 

Error 처리할때 사용할 enum도 만들어주고 sink를 만들어줍니다!

 

failure부터 사용해보겠습니다!

relay.send("Hello")
relay.send(completion: .failure(SojinError.unknown))
relay.send("Sojin")

[출력]
PassthroughSubject 데이터: Hello
에러 삐용삐용
The operation couldn’t be completed. (__lldb_expr_77.SojinError error 0.)

 

Sojin이 출력이 안되고 에러 처리되는걸 볼 수 있죠?

 

그렇다면 finished는?

 

relay.send("Hello")
relay.send(completion: .finished)
relay.send("Sojin")


[출력]
PassthroughSubject 데이터: Hello
finished

 

동일하게 Sojin은 출력 안되고

 

설정해놨던 finished를 프린트하고

종료됐네요!

 

subscription은 

구독자에게 구독을 보내는 역할을 한다는데..

출력하는 역할인가..

구글링해도 잘 안나와서

모르겠네요ㅠㅠ

알게되면 다시 설명 추가하도록하겠습니다! : )

 

 

코드

https://github.com/sojin2/Combine

 

GitHub - sojin2/Combine: Combine을 공부하는 공간입니다.

Combine을 공부하는 공간입니다. Contribute to sojin2/Combine development by creating an account on GitHub.

github.com

 

'iOS > Combine' 카테고리의 다른 글

[Combine] - Publisher, Subscriber  (1) 2023.01.16