[swift] IGListDiffKit을 이용한 바인딩 작업

IGListDiffKit은 iOS에서 데이터 바인딩을 간편하게 수행할 수 있는 라이브러리입니다. 이 라이브러리는 IGListKit의 일부로 동작하며, 다양한 컬렉션 뷰 구성요소와 함께 사용할 수 있습니다. 이번 포스트에서는 IGListDiffKit을 이용하여 데이터를 바인딩하는 방법에 대해 알아보겠습니다.

IGListDiffKit 소개

IGListDiffKit은 효율적으로 컬렉션 뷰를 업데이트하기 위해 다음과 같은 특징을 가지고 있습니다:

IGListDiffKit 설치

IGListDiffKit은 CocoaPods를 통해 쉽게 설치할 수 있습니다. Podfile에 다음과 같이 추가한 후 pod install을 실행하세요:

pod 'IGListDiffKit'

바인딩 작업 예시

IGListDiffKit을 이용한 바인딩 작업을 예시를 통해 알아보겠습니다.

  1. IGListDiffable 프로토콜을 준수하는 모델 객체를 만듭니다.
class Item: NSObject, IGListDiffable {
    let id: String
    let name: String
    
    init(id: String, name: String) {
        self.id = id
        self.name = name
    }
    
    // MARK: - IGListDiffable
    
    func diffIdentifier() -> NSObjectProtocol {
        return id as NSObjectProtocol
    }
    
    func isEqual(toDiffableObject object: IGListDiffable?) -> Bool {
        guard let object = object as? Item else {
            return false
        }
        return id == object.id && name == object.name
    }
}
  1. IGListAdapterDataSource를 구현하여 데이터를 제공합니다.
class MyViewController: UIViewController, IGListAdapterDataSource {

    let items: [Item] = [
        Item(id: "1", name: "Item 1"),
        Item(id: "2", name: "Item 2"),
        Item(id: "3", name: "Item 3")
    ]
    
    lazy var adapter: ListAdapter = {
        return ListAdapter(updater: ListAdapterUpdater(), viewController: self)
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        adapter.dataSource = self
        adapter.collectionView = collectionView
    }

    // MARK: - IGListAdapterDataSource
    
    func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
        return items
    }
    
    func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
        return MySectionController()
    }
    
    func emptyView(for listAdapter: ListAdapter) -> UIView? {
        return nil
    }
}

class MySectionController: ListSectionController {
    
    var item: Item?
    
    override func sizeForItem(at index: Int) -> CGSize {
        guard let item = item else {
            return .zero
        }
        return CGSize(width: collectionContext!.containerSize.width, height: 50)
    }
    
    override func cellForItem(at index: Int) -> UICollectionViewCell {
        let cell = collectionContext!.dequeueReusableCell(of: MyCell.self, for: self, at: index) as! MyCell
        cell.titleLabel.text = item?.name
        return cell
    }
    
    override func didUpdate(to object: Any) {
        item = object as? Item
    }
}

예시에서는 Item 클래스가 IGListDiffable 프로토콜을 준수하도록 구현되었습니다. MyViewController 클래스에서는 IGListAdapterDataSource를 구현하여 컬렉션 뷰에 데이터를 제공하고, listAdapter(_:sectionControllerFor:) 메서드에서 섹션 컨트롤러를 반환합니다. MySectionController 클래스는 각각의 아이템에 대한 섹션을 관리합니다.

  1. 바인딩 작업이 수행되는 메서드에서 업데이트를 수행합니다.
class MyViewModel {
    var items: [Item] = [
        Item(id: "1", name: "Item 1"),
        Item(id: "2", name: "Item 2"),
        Item(id: "3", name: "Item 3")
    ]
    
    func updateItems(with newItems: [Item]) {
        // IGListDiffKit을 이용하여 데이터 업데이트를 수행합니다.
        let result = IGListDiff(oldArray: items, newArray: newItems, option: .equality)
        let updates = result!.updates(in: items, from: 0)

        items = newItems
        
        adapter.performUpdates(animated: true)
    }
}

// 바인딩 작업이 수행되는 메서드에서 IGListDiffKit을 이용하여 업데이트를 수행합니다.
let newItems = [
    Item(id: "1", name: "Updated Item 1"),
    Item(id: "2", name: "Updated Item 2"),
    Item(id: "4", name: "New Item")
]
viewModel.updateItems(with: newItems)

위의 코드에서 updateItems(with:) 메서드에서 IGListDiffKit을 이용하여 데이터 업데이트를 수행하고, adapter.performUpdates(animated:) 메서드를 호출하여 변경 사항을 컬렉션 뷰에 적용합니다.

이로써 IGListDiffKit을 이용한 데이터 바인딩 작업이 완료되었습니다. IGListDiffKit은 데이터의 변경 사항을 효율적으로 처리하고, 성능 향상을 제공하여 사용자에게 원활한 경험을 제공할 수 있습니다.