[swift] IGListDiffKit과 함께하는 필터링과 정렬

IGListDiffKit은 iOS 앱에서 복잡한 데이터의 변경 사항을 처리하기 위한 강력한 라이브러리입니다. 이 라이브러리는 UICollectionView와 함께 사용되며, 데이터의 변경을 효율적으로 처리하고 화면 갱신을 최소화할 수 있게 도와줍니다.

이번에는 IGListDiffKit을 사용하여 데이터의 필터링과 정렬을 적용하는 방법에 대해 알아보겠습니다.

필터링

데이터의 필터링은 주어진 조건에 맞는 항목만을 보여주는 기능입니다. IGListDiffKit은 IGListBindingSectionController라는 클래스를 제공하여 이를 쉽게 구현할 수 있습니다.

먼저, 필터링을 적용할 데이터 모델과 섹션 컨트롤러를 준비합니다. 데이터 모델은 다음과 같이 구성할 수 있습니다.

struct Item {
    let name: String
    let category: String
    // ...
}

필터링에 사용할 조건을 표현하는 열거형을 만들어줍니다.

enum Filter {
    case all
    case category(String)
}

섹션 컨트롤러에서는 필터를 적용하여 해당하는 항목만 화면에 표시하는 로직을 작성합니다. IGListBindingSectionControllerviewModels 프로퍼티를 활용하여 필터링된 데이터를 반환하면 됩니다.

class MySectionController: IGListBindingSectionController<Item>, IGListBindingSectionControllerDataSource {
    
    var filter: Filter = .all
    
    override init() {
        super.init()
        dataSource = self
    }
    
    // ...
    
    func listAdapter(_ listAdapter: IGListAdapter, viewModelsFor object: Any) -> [IGListAdapterViewModel] {
        guard let items = object as? [Item] else { return [] }
        
        var filteredItems: [Item]
        
        switch filter {
        case .all:
            filteredItems = items
        case .category(let category):
            filteredItems = items.filter { $0.category == category }
        }
        
        return filteredItems.map { IGListAdapterViewModel(value: $0, reuseIdentifier: "ItemCell") }
    }
}

필터링을 변경하기 위해 적절한 이벤트 (예: 버튼 탭)를 처리하여 filter 프로퍼티를 업데이트하고, 섹션 컨트롤러의 IGListBindingSectionControllerDataSource 메서드가 호출되도록 해야 합니다.

정렬

데이터의 정렬은 항목들을 특정 기준에 따라 순서대로 나열하는 기능입니다. IGListDiffKit은 IGListSortingDelegate 프로토콜을 사용하여 정렬 기능을 제공합니다.

먼저, 정렬에 사용할 항목의 키를 표현하는 열거형을 만들어줍니다.

enum SortKey {
    case name
    case category
    // ...
}

정렬에 대한 사용자 설정은 UserDefaults를 이용하여 저장하고, 각각의 키에 대해 정렬 순서를 지정할 수 있도록 합니다.

func setSortOrder(_ sortOrder: SortOrder, forKey key: SortKey) {
    let userDefaults = UserDefaults.standard
    userDefaults.set(sortOrder.rawValue, forKey: key.rawValue)
    userDefaults.synchronize()
}

func getSortOrder(forKey key: SortKey) -> SortOrder {
    let userDefaults = UserDefaults.standard
    let rawValue = userDefaults.integer(forKey: key.rawValue)
    return SortOrder(rawValue: rawValue) ?? .ascending
}

섹션 컨트롤러에서는 정렬된 데이터를 반환하는 로직을 작성합니다.

class MySectionController: IGListBindingSectionController<Item>, IGListBindingSectionControllerDataSource, IGListSortingDelegate {
    
    var sortKey: SortKey = .name
    
    override init() {
        super.init()
        dataSource = self
        sortingDelegate = self
    }
    
    // ...
    
    func listAdapter(_ listAdapter: IGListAdapter, viewModelsFor object: Any) -> [IGListAdapterViewModel] {
        guard let items = object as? [Item] else { return [] }
        
        let sortedItems: [Item]
        
        switch sortKey {
        case .name:
            sortedItems = items.sorted { $0.name < $1.name }
        case .category:
            sortedItems = items.sorted { $0.category < $1.category }
        }
        
        return sortedItems.map { IGListAdapterViewModel(value: $0, reuseIdentifier: "ItemCell") }
    }
    
    // MARK: - IGListSortingDelegate
    
    func listAdapter(_ listAdapter: IGListAdapter, move object: Any, from previousObjects: [Any], to previousObjects: [Any]) -> [Any] {
        guard let items = previousObjects as? [Item] else { return previousObjects }
        
        let sortedItems: [Item]
        
        switch sortKey {
        case .name:
            sortedItems = items.sorted { $0.name < $1.name }
        case .category:
            sortedItems = items.sorted { $0.category < $1.category }
        }
        
        return sortedItems
    }
}

사용자 설정 UI에서 필터링과 정렬 설정을 변경하는 메서드를 구현하여 섹션 컨트롤러의 filtersortKey 프로퍼티를 업데이트하면 됩니다.

결론

IGListDiffKit을 사용하면 다양한 데이터의 필터링과 정렬 기능을 쉽게 구현할 수 있습니다. 필요한 데이터 변경 사항을 빠르고 효율적으로 처리하여 사용자에게 더 좋은 경험을 제공할 수 있습니다.

더 자세한 내용은 IGListDiffKit GitHub 페이지를 참고하세요.