ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Combine] Publishers 를 합쳐서 한번에 처리해주자 - combineLatest
    Swift 2023. 1. 13. 23:56

    이런 화면을 구현하고 싶습니다 👇👇

    입력받은 텍스트로 결괏값을 필터해서 맞는 결과를 보여주는 것입니다

    ✅ 구현1 - didSet

    예전에 저 같았으면 아마도 아래와 같은 로직으로 코드를 짰을 것 같습니다 👇👇

    (검증된 코드가 아닙니다 그냥 대충 이런식으로 했을것 같다~ 입니다)

    searchText 가 입력될때 마다 didSet 이 실행되고 거기서 필터하고..

    하지만 경험상 이렇게 되면 굉장히 지저분해지니다.

    왜냐? Property 에 저렇게 didSet 이 달리고 달리고 하면서 이게 intent 도 많아지고 한눈에 봤을때 안읽히는 문제가 있습니다

    그럼 어떻게 해야할까요?

    final class HomeViewModel: ObservableObject {
    
        private let dataService = CoinDataService()
        @Published var coins: [CoinModel] = []
        @Published var portfolioCoins: [CoinModel] = []
        @Published var searchText = "" {
        	didSet {
            	self.coins = filterCoins(text: searchText, coins: dataService.coins)
            }
        }
        
        private func filterCoins(text: String, coins: [CoinModel]) -> [CoinModel] {
            guard !text.isEmpty else { return coins }
            let lowercased = text.lowercased()
            let filtered = coins.filter {
                $0.name.lowercased().contains(lowercased) ||
                $0.id.lowercased().contains(lowercased) ||
                $0.symbol.lowercased().contains(lowercased)
            }
            return filtered
        }
    }

    ✅ 구현2 - combineLatest

    이런식으로 쓰면 굉장히 편해집니다~!

    일단 한눈에 봤을때 어떤가요? 굉장히 편해지지 않았나요?

    좀더 함수형에 가까워진 기분도 들고 뭐 좋은것 같습니다

    그럼 코드를 하나씩 까보면서 어떻게 구현된건지 읽어보겠습니다.

    searchText에 변화가 있으면 계속 호출이 될꺼에요.

    근데 서버에서 값이 받아져왔을 때도 값에 대한 변화를 주고 싶어요!

    그러면 이렇게 하시면 됩니다. 바로 두 값에 변화가 있을때 마다 하나로 묶어서 한번에 처리를 해주는 거에요.

    .combineLatest 는 이럴때 사용하는 메써드입니다. 다수의 Publisher에 변화가 있을때 한번에 처리를 해주는 거에요.

    자 이렇게 코드를 작성하게 된다면 tuple 로 String 과 [CoinModel] 이 들어옵니다.

    그리고 그걸 filterCoins 에 넘겨주고 있어요. 한번에 처리하니까 너무 깔끔하죠? 

    didSet 의 겹겹이 쌓인 들여쓰기도 없고 너무 깔끔한것 같아요

    아래는 공식문서인데 Publishers 가 최소한 한개의 요소를 던져줘야만 호출이 된다 뭐 이런 말을 하고 있네요.

Designed by Tistory.