티스토리 뷰

Combine

CombineLatest

밀쿄 2020. 2. 11. 10:38

안녕하세요. 밀쿄입니다,

오랜만에 Combine 관련으로 글 쓰는 것 같네요.

오늘은 결합 연산자 중에 제일 많이 사용하게 되는 CombineLatest에 대해서 알아보겠습니다.

일단 조금 이상한 예제지만 CombineLatest 전후를 비교하기 위해서 예제를 하나만 비교해보겠습니다,.

두 개의 배열이 있고 이 배열이 count가 일정 갯수이상 되면 콘솔창에 메세지를 출력하는 예제입니다.

먼저 콤바인 없는 상태입니다.

class TestClassWithoutCombine {
    var items = [String]() {
        didSet {
            self.isPass = items.count > 3 && items2.count > 1
        }
    }
    var items2 = [String]() {
        didSet {
            self.isPass = items.count > 3 && items2.count > 1
        }
    }
    
    var isPass: Bool = false {
        didSet {
            if self.isPass {
                self.showMessage()
            }
        }
    }
    
    func inputDataAtItems() {
        self.items.append("Hello")
    }
    
    func inputDataAtItems2() {
        self.items2.append("World")
    }
    
    func showMessage() {
        print("Goal")
    }
}
//let testClassWithoutCombine = TestClassWithoutCombine()
//testClassWithoutCombine.inputDataAtItems()
//testClassWithoutCombine.inputDataAtItems()
//testClassWithoutCombine.inputDataAtItems()
//testClassWithoutCombine.inputDataAtItems()
//testClassWithoutCombine.inputDataAtItems2()
//testClassWithoutCombine.inputDataAtItems2()
//Goal

실제로 콤바인 없었을때 제가 didSet을 이용해서 구현해서 사용했었습니다.

자 이제 이 코드를 콤바인으로 바꿔보겠습니다,

class TestClass {
    @Published var items = [String]()
    @Published var items2 = [String]()
    var cancelBag = [AnyCancellable]()
    
    init() {
        Publishers.CombineLatest($items, $items2)
            .filter{ $0.count > 3  && $1.count > 1}
            .sink { _ in self.showMessage() }
            .store(in: &self.cancelBag)
    }
    
    func inputData() {
        self.items.append("Hello")
    }
    
    func inputData2() {
        self.items2.append("World")
    }
    
    func showMessage() {
        print("Goal")
    }
}

//let test = TestClass()
//test.inputData()
//test.inputData()
//test.inputData()
//test.inputData()
//test.inputData2()
//test.inputData2()
//Goal

이렇게 콤바인으로 작성할 수 있지만 아래처럼도 작성할 수 있습니다,

class TestClass {
    @Published var items = [String]()
    @Published var items2 = [String]()
    var cancelBag = [AnyCancellable]()
    
    init() {        
        $items
            .combineLatest($items2){$0.count > 3 && $1.count>1}
            .filter{$0 == true}
            .sink { _ in self.showMessage() }
            .store(in: &self.cancelBag)
    }
    
    func inputData() {
        self.items.append("Hello")
    }
    
    func inputData2() {
        self.items2.append("World")
    }
    
    func showMessage() {
        print("Goal")
    }
}

//let test = TestClass()
//test.inputData()
//test.inputData()
//test.inputData()
//test.inputData()
//test.inputData2()
//test.inputData2()
//Goal

위 아래 코드의 차이점이라면 같은 결합연산자지만 맡에꺼는 CombineLatest + Map의 느낌이 강합니다

실제로 아래 연산자를 애플문서에서 찾아보면 리턴타입이  CombineLatest + Map 입니다.

https://developer.apple.com/documentation/combine/publishers/combinelatest/3333799-combinelatest

 

combineLatest(_:_:) - Publishers.CombineLatest | Apple Developer Documentation

Generic Instance Method combineLatest(_:_:) Subscribes to an additional publisher and invokes a closure upon receiving output from either publisher. DeclarationParametersotherAnother publisher to combine with this one.transformA closure that receives the m

developer.apple.com

개인적으로 위에 처럼 결합한 배열을 사용하지 않고

특정값으로 바꿔서 무언가를 할 경우라면 밑에 방법이 조금 더 직관적이라는 생각이 듭니다.

( 이 예시에서는 bool값으로 바꿔서 true일 때 showMessage를 실행해줬습니다. )

그리고 CombineLatest는 최대 4개까지 결합할 수 있습니다.

4개 이상 연결하고 싶으면 CombineLatest끼리 결합하면 될 것 같습니다.

크게 어렵지 않은 연산자지만 실제로 꽤 많이 사용하는 연산자라 생각되니 잘 익혀두면 좋을 것 같습니다.

'Combine' 카테고리의 다른 글

Publisher & Subscriber  (0) 2020.02.19
Combine을 시작하기 전에  (0) 2020.02.14
[Combine] Sequence  (0) 2019.12.20
[Combine]Just  (0) 2019.12.16
[Combine] Scheduler  (0) 2019.12.15
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함