How to update realm with diffabledatasource?

181 Views Asked by At

I'm new to realm and trying to implement realm with UICollectionViewDiffableDataSource. However, I'm finding it difficult to update the data source after inserting / deleting a new object. I tried to update with NotificationToken but it crashes. Here's the code that I've tried so far:

fileprivate let realm = try! Realm()
fileprivate var notificationToken: NotificationToken?
fileprivate var items: Results<Item>?

fileprivate enum Section: String, CaseIterable, Hashable {
    case main
}
fileprivate typealias DataSource = UICollectionViewDiffableDataSource<Section, Item>
fileprivate typealias Snapshot = NSDiffableDataSourceSnapshot<Section, Item>

fileprivate lazy var dataSource = itemsDataSource()

fileprivate func itemsDataSource() -> DataSource {
    let dataSource = DataSource(collectionView: itemsCollectionView) { collectionView, indexPath, item in
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! STItemCell
        cell.titleLabel.text = item.name
        return cell
    }
    return dataSource
}

fileprivate func bind() {
    items = realm.objects(Item.self).sorted(byKeyPath: "order").filter("isDeleted == false")
        
    notificationToken = items?.observe({ [weak self] changes in
        guard let datasource = self?.datasource else { return }
            switch changes {
            case .initial:
                self?.applySnapshot()
            case .update(_, deletions: let deletions, insertions: let insertions, modifications: let modifications):
                var snapshot = datasource.snapshot()
                
                if !deletions.isEmpty {
                    let itemIdentifiers = deletions.compactMap { item in
                        return datasource.itemIdentifier(for: IndexPath(item: item, section: 0))
                    }
                    snapshot.deleteItems(itemIdentifiers)
                }
                
                if !insertions.isEmpty {
                    let itemIdentifiers = insertions.compactMap { item in
                        return datasource.itemIdentifier(for: IndexPath(item: item, section: 0))
                    }
//                    snapshot.insertItems(...) // Don't know how to implement this...
                }
                
                if !modifications.isEmpty {
                    let itemIdentifiers = modifications.compactMap { item in
                        return datasource.itemIdentifier(for: IndexPath(item: item, section: 0))
                    }
                    snapshot.reloadItems(itemIdentifiers)
                }
                
                datasource.apply(snapshot, animatingDifferences: true)
            case .error(let error):
                fatalError("\(error)")
            }
     })
}


fileprivate func applySnapshot(animatingDifferences: Bool = true) {
     var snapshot = Snapshot()
     snapshot.appendSections([.main])
     guard let items = items else { return }
     snapshot.appendItems(Array(items))
     datasource.apply(snapshot, animatingDifferences: animatingDifferences)
}

Would really appreciate your help regarding this. Thanks!

0

There are 0 best solutions below