iOS13+, UITableViewDiffableDataSource

Lena·2021년 5월 2일
0
post-custom-banner

What is UITableViewDiffableDataSource?

iOS 13+ 부터 UITableViewDataSource을 대신해 table view에 어떤 cell을, 얼마나(how many), 어느 section에 display 할 지 등을 configure 할 수 있는 UITableViewDiffableDataSource가 지원됩니다.
(UICollectionViewDiffableDataSource도 마찬가지)

기존 UITableViewDataSource를 사용하는 방식과 가장 큰 차이점은 reloadData, performBatchUpdates가 없다는 것입니다.

UITableViewDiffableDataSource은 data에 변화가 생길 경우, update 이전과 이후를 비교해서 animate 합니다.

The diffable part of UICollectionViewDiffableDataSource means that whenever you update the items you’re displaying, the collection view will automatically calculate the difference between the updated collection and the one previously shown. This will in turn cause the collection view to animate the changes, such as updates, insertions and deletions.

Benefits

UITableViewDiffableDataSource를 사용해서 얻는 이점은

  • data 변화를 사용자가 인지할 수 있는 애니메이션이 지원됩니다.
  • 자동으로 데이터가 동기화(synchronization) 됩니다.
  • 전체적으로 작성하는 코드의 양을 줄일 수 있습니다.
  • Automatic data change animations: Whenever you add, update or delete data, you can get the data change animation automatically.
  • Automatic data synchronization: To utilize collection view’s standard animation without UICollectionViewDiffableDataSource, you’d have to manually manage and synchronize data changes between the collection view and the data source. If you have a misalignment in one of the synchronization operations, you’d see an error like this:
    Assertion error because the collection view update is invalid
  • Reduced code: Overall, you can write less code and benefit from the collection view’s data change animations and data synchronization.

Using Diffable Data Source

  • Hashable section, item
  • UICollectionViewDiffableDataSource
  • NSDiffableDataSourceSnapshot

1️⃣ Hashable Section type, Item type 선언

UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType> : NSObject where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable

UITableViewDiffableDataSource은 위와 같은 형태의 generic class이므로, section과 item이 될 Hashable한 객체를 선언해야 합니다.
UITableViewDiffableDataSource은 Snapshot 객체를 이용해 data의 변화를 감지하는데, Snapshot이 indexPath 대신 unique identifiers에 의존하기 때문에 section과 item type은 Hashable protocol을 준수하는 타입이어야 합니다.

class Section: Hashable {
    var id = UUID()
    var title: String
    var item: [Dish]
    
    init(title: String, item: [Dish]) {
        self.title = title
        self.item = item
    }
    
    func hash(into hasher: inout Hasher) {
       hasher.combine(id)
     }
     
     static func == (lhs: Section, rhs: Section) -> Bool {
       lhs.id == rhs.id
     }
}


class Dish: Decodable {
    let detailHash: String
    let title: String
}

extension Dish: Hashable {
    static func == (lhs: Dish, rhs: Dish) -> Bool {
        return lhs.detailHash == rhs.detailHash
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(detailHash)
    }
}

2️⃣ UITableViewDiffableDataSource 생성
UITableViewDiffableDataSource의 initializer로

  • dataSource와 연결할 tableView와,
  • cellProvider(escaping closure 형태)를 제공해야 합니다.
    UITableViewDataSourcecellForRowAt: 메서드를 구현하는 것과 유사합니다.
func makeDataSource() -> UITableViewDiffableDataSource<Section, Dish> {
    let reuseIdentifier = cellReuseIdentifier
    return UITableViewDiffableDataSource(
        tableView: tableView,
        cellProvider: { tableView, indexPath, dish in
            let cell = tableView.dequeueReusableCell(
                withIdentifier: reuseIdentifier,
                for: indexPath)
                
            cell.textLabel?.text = dish.title
            
            return cell
        }
    )
}

3️⃣ NSDiffableDataSourceSnapshot 생성
NSDiffableDataSourceSnapshot 객체를 통해 dataSource가 data의 변화를 감지합니다.

func updateSnapshot(animatingChange: Bool = false) {
    var snapshot = NSDiffableDataSourceSnapshot<Section, Dish>()
        
    snapshot.appendSections(sections)
    sections.forEach { section in
      snapshot.appendItems(section.item, toSection: section)
    }
    dataSource.apply(snapshot, animatingDifferences: animatingChange)
}

https://www.appcoda.com/diffable-data-source/
https://www.raywenderlich.com/8241072-ios-tutorial-collection-view-and-diffable-data-source

post-custom-banner

0개의 댓글