[swift] RxDataSources의 필터링 및 정렬 기능 활용 방법

소개

RxDataSources는 RxSwift를 기반으로 한 iOS 애플리케이션에서 테이블뷰나 컬렉션뷰의 데이터소스를 관리하기 위해 사용하는 라이브러리입니다. 이 라이브러리는 데이터소스를 선언형으로 정의할 수 있기 때문에 데이터 변화에 대한 반응적인 업데이트를 쉽게 다룰 수 있습니다.

이번 블로그 포스트에서는 RxDataSources를 활용하여 테이블뷰의 필터링 및 정렬 기능을 구현하는 방법을 알아보겠습니다.

필터링 기능

Step 1: 필터링 로직을 구현하기 위해 BehaviorRelay 타입의 필터링용 변수를 선언합니다. 예를 들어, 문자열 배열을 테이블뷰에 표시하고 해당 문자열을 필터링하여 특정 조건에 맞는 것만 표시하고 싶다면, 다음과 같이 필터링용 변수를 선언할 수 있습니다.

let filteringText = BehaviorRelay<String?>(value: nil)

Step 2: 데이터소스 인스턴스를 초기화하고 필터링 로직에 따라 데이터를 처리합니다. 필터링 로직은 filter 메서드를 사용하여 수행할 수 있습니다. 예를 들어, filteringText 변수에 값이 설정되면 해당 값과 일치하는 문자열만 필터링된 데이터로 업데이트하는 코드는 다음과 같습니다.

let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, String>>(
    configureCell: { _, tableView, indexPath, item in
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = item
        return cell
    }
)

filteringText
    .asObservable()
    .map { filterText in
        return originalData.filter { $0.contains(filterText ?? "") }
    }
    .bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: disposeBag)

정렬 기능

Step 1: 정렬 로직을 구현하기 위해 BehaviorRelay 타입의 정렬용 변수를 선언합니다. 예를 들어, 어떤 조건에 따라 순서를 변경하고 싶다면, 다음과 같이 정렬용 변수를 선언할 수 있습니다.

let sortingOption = BehaviorRelay<SortingOption>(value: .ascending)

Step 2: 데이터소스 인스턴스를 초기화하고 정렬 로직에 따라 데이터를 처리합니다. 정렬 로직은 sorted 메서드를 사용하여 수행할 수 있습니다. 예를 들어, sortingOption 변수에 따라 데이터를 오름차순 또는 내림차순으로 정렬하는 코드는 다음과 같습니다.

sortingOption
    .asObservable()
    .map { option in
        switch option {
        case .ascending:
            return originalData.sorted()
        case .descending:
            return originalData.sorted(by: >)
        }
    }
    .bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: disposeBag)

결론

이와 같은 방법으로 RxDataSources를 활용하여 테이블뷰의 필터링 및 정렬 기능을 손쉽게 구현할 수 있습니다. 필터링 및 정렬 기능을 함께 사용한다면, 이를 조합하는 코드도 작성할 수 있습니다. RxDataSources의 선언형 접근 방식과 RxSwift의 반응성을 활용하면, 데이터소스 관리에 대한 복잡함을 크게 줄일 수 있습니다.

더 자세한 내용은 RxDataSources 공식 문서를 참조하시기 바랍니다.

enum SortingOption {
    case ascending
    case descending
}

let originalData = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]
let filteringText = BehaviorRelay<String?>(value: nil)
let sortingOption = BehaviorRelay<SortingOption>(value: .ascending)

let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, String>>(
    configureCell: { _, tableView, indexPath, item in
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = item
        return cell
    }
)

filteringText
    .asObservable()
    .map { filterText in
        return originalData.filter { $0.contains(filterText ?? "") }
    }
    .bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: disposeBag)

sortingOption
    .asObservable()
    .map { option in
        switch option {
        case .ascending:
            return originalData.sorted()
        case .descending:
            return originalData.sorted(by: >)
        }
    }
    .bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: disposeBag)

참고 자료