본문 바로가기

Combine

[Combine] SwiftUI 에서는 Publisher 를 어떻게 구독할까?

안녕하세요.

이전 글에서 Publisher, Subscriber 를 

구독하는 방법에 대해 알아봤습니다.

 

이번엔 SwiftUI 에서는 어떻게 구독하는지에 대해

알아보려합니다.

 

크게 3가지로 알아보겠습니다.

1. onReceive

2. ObservableObject & @Published

3. ViewModifier 사용


1. onReceive

 

onReceive는 SwiftUI 에서

가장 간단한 Publisher 구독 방법이라 볼 수 있습니다.

 

struct ContentView: View {
    @State private var data: String = "🌧️"
    private var cancellables: Set<AnyCancellable> = []
    
    let somePublisher = Just("🌈")
    
    var body: some View {
        Text(data)
            .onAppear {
                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                    somePublisher
                        .sink { newData in
                            withAnimation {
                                self.data = newData
                            }
                        }
                        .cancel()
                }
            }
    }
}

 

보시는 것 처럼 onAppear 메서드를 사용해서

그 안에서 Publisher 를 sink 하여 구독 처리를

진행할 수 있습니다.

 

코드를 실행해보면

 🌧️ 모양이 나오다가 2초가 지나면

🌈 모양이 나타나는 것을 확인할 수 있습니다.

 

 

2. ObservableObject & @Published

 

class DataModel: ObservableObject {
    @Published var data: String = "☀️"
    
    init() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.data = "🌖"
        }
    }
}

struct TestView: View {
    
    @ObservedObject var model = DataModel()
    
    var body: some View {
        Text(model.data)
    }
}

 

위와같이 data 프로퍼티 앞에 @Published 키워드를 추가해주면서

Publisher 의 역할을 할 수 있게 됩니다.

@Published 된 값에 접근하기 위해선

DataModel 인터페이스를 사용하는 곳에서

@ObservedObject 키워드를 작성하여

data 프로퍼티에 접근하게 됩니다.

 

(@ObservedObject 에 대한 자세한 설명은

이곳에 작성해뒀습니다)

 

 

3. ViewModifier 사용

 

struct DataPublisherModifier: ViewModifier {
    
    @State private var data: String = "🌧️"
    let somePublisher = Just("🌈")

    func body(content: Content) -> some View {
        content
            .onAppear {
                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                    somePublisher
                        .sink { newData in
                            withAnimation {
                                self.data = newData
                            }
                        }
                        .cancel()
                }
            }
            .overlay(Text(data)
            .font(.title)
            .foregroundColor(.white))
    }
}

struct SubscribePublisher3: View {
    var body: some View {
        Text("Rainy Day")
            .modifier(DataPublisherModifier())
    }
}

 

ViewModifier 를 채택하는 방식으로 

Publisher 를 사용할 수 있습니다.

이렇게 작성하면

첫번째 방법으로 소개드렸던 onReceive 와는 다르게

body 안에서 sink 하지 않고

외부 메서드에서 sink 를 진행하는 형태로

변경할 수 있습니다.

 

추가적으로, Modifier 라는 명칭은

SwiftUI 에서 사용되는 용어로

SwiftUI 뷰의 모양과 동작을 수정 or 변환하는데

사용되는 뷰의 속성을 의미합니다.

 

(Modifier 관련 내용은 추후 포스팅하도록 하겠습니다.)

 

지금까지

SwiftUI 에서 Publisher 를 구독하는 방법을

알아봤는데 작성한 예제가 적절할까? 에 대해선 

의구심이 드네요.. 좀 더 괜찮은 예제가 있다면

글을 수정해보도록 하겠습니다.

 

읽어주셔서 감사합니다!