API에서 받은 코인 리스트 중에 유저가 원하는 키워드를 갖고 있는 코인만 보여주는 기능입니다.
HomeViewModel.swift 에 filtering 함수를 작성해줍니다.
import Foundation
import Combine
class HomeViewModel: ObservableObject {
@Published var allCoins: [CoinModel] = []
@Published var searchCoins: [CoinModel] = [] <- 필터링 된 리스트를 받을 어레이
@Published var portfolioCoins: [CoinModel] = []
@Published var searchText: String = ""
private let dataService = CoinDataService()
private var cancellables = Set<AnyCancellable>()
init() {
addSubscribers()
}
func addSubscribers() {
// AllCoins Update
dataService.$allCoins
.sink { [weak self] (returnedCoins) in
self?.allCoins = returnedCoins
}
.store(in: &cancellables)
// Search Filtering
$searchText // Subcriber
.combineLatest(dataService.$allCoins) // Subcriber
.debounce(for: .seconds(0.3), scheduler: DispatchQueue.main)
// .debounce는 유저가 아무리 빠르게 타이핑해도 0.3초에 한번씩만 수행되도록 한다. 만약 설정하지 않는다면 유저가 빠르게 10자를 타이핑할 시 10번을 새롭게 수행하게 된다. 때문에 큰 데이터라면 좋지 않다.
.map(filterCoins)
.sink { [weak self] (returnCoins) in
self?.searchCoins = returnCoins
}
.store(in: &cancellables)
}
private func filterCoins(text: String, coins: [CoinModel]) -> [CoinModel] {
// text가 비어있지 않을 때만 계속 진행, 비어있다면 coins를 리턴하라
guard !text.isEmpty else {
return coins
}
// 입력된 문자를 소문자로 변환
let lowercasedText = text.lowercased()
// StartingCoins를 순회하며 조건값으로 필터링하고 리턴하라
return coins.filter { (coin) -> Bool in
// 요소의 name, symbol, id에 lowercasedText를 포함한 것을 반환하라
return coin.name.lowercased().contains(lowercasedText) || // || 는 or "혹은"이라는 뜻
coin.symbol.lowercased().contains(lowercasedText) ||
coin.id.lowercased().contains(lowercasedText)
}
}
}
흐름을 정리한다면
1. 두가지 Subscriber를 통해 유저가 입력할 텍스트필드의 내용과 코인리스트를 가져옵니다.
2. debounce를 작성하여 혹시나 발생할 수 있는 유저의 과입력(?)을 방지해줍니다.
3. map(filterCoins)를 통해 filterCoins의 조건으로 코인 리스트를 필터링합니다.
4. sink로 searchCoins 어레이에 최종 전달!
이번 필터링을 구현할 때의 공부는 배운게 많고 유익했습니다.
이로써 검색화면의 기능들이 거의 다 구현된 것 같아서 기쁘네요! ^^
'Project > SwiftUI 블록와이드' 카테고리의 다른 글
[SwiftUI Project] Scroll To Top 버튼 만들기 (0) | 2022.09.18 |
---|---|
[SwiftUI Project] Sticky Header 만들기 (0) | 2022.09.18 |
[SwiftUI Project] TextField FirstResponder 텍스트필드 포커싱 하기 (0) | 2022.09.16 |
[SwiftUI Project] 다른 View를 탭하거나 스크롤 하면 키보드 내리기 (0) | 2022.09.16 |
[SwiftUI Project] 검색화면 전환 개선하기 GeometryReader (0) | 2022.09.15 |
댓글