Swift - What is the difference between implementing Hashable and Equatable and NSObject hash and isEqual overrides

353 views Asked by At

I'm trying to wrap my head around the new DiffableDataSource way of handling data in tableviews/collectionviews and during testing I came across a strange crash. I would expect that the two implementations below would work exactly the same:

Implementation 1:

class DiffableSection {

    var id: String
    var items: [AnyDiffable]

    init(id: String,
         items: [AnyDiffable] = []) {
        self.id = id
        self.items = items
    }
}

extension DiffableSection: Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

extension DiffableSection: Equatable {
    static func == (lhs: DiffableSection, rhs: DiffableSection) -> Bool {
        return lhs.id == rhs.id
    }
}

Implementation 2:

class DiffableSection: NSObject {

    var id: String
    var items: [AnyDiffable]

    init(id: String,
         items: [AnyDiffable] = []) {
        self.id = id
        self.items = items
    }

    // MARK: - Hashable and Equatable

    public override var hash: Int {
        var hasher = Hasher()
        hasher.combine(id)
        return hasher.finalize()
    }

    public override func isEqual(_ object: Any?) -> Bool {
        guard let object = object as? DiffableSection else { return false }
        return id == object.id
    }
}

but apparently they are not - Implementation 2 works with the code below and Implementation 1 does not.

    func apply(_ sections: [DiffableSection]) {
        var snapshot = self.snapshot()
        for section in sections {
            snapshot.appendSectionIfNeeded(section)
            snapshot.appendItems(section.items, toSection: section)
        }
        apply(snapshot)
    }

(...)
extension NSDiffableDataSourceSnapshot {
    mutating func appendSectionIfNeeded(_ identifier: SectionIdentifierType) {
        if sectionIdentifiers.contains(identifier) { return }
        appendSections([identifier])
    }
}

The crash message I get when running with Implementation 1:

'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: section != NSNotFound'

Can someone explain me what are the differences in those implementations? How could I fix Implementation 1 to work same as Implementation 2??

0

There are 0 answers