ra1028 / DifferenceKit

💻 A fast and flexible O(n) difference algorithm framework for Swift collection.

Home Page:https://ra1028.github.io/DifferenceKit

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Delete/Insert vs. Update

cnstoll opened this issue · comments

Hi,

I love this library, but I'm having trouble figuring out the best practice for triggering an "update" to an existing element at a given location, versus having it be deleted and inserted. In my model, I'm just making a slight change to an element at a certain indexPath, and I'd like it to reload just that item instead of deleting the item and re-inserting it.

I'm assuming the problem is with my hashable or equatable implementation. Maybe I'm telling the library something wrong that's causing it to see an update as a delete/insert?

For a given item that implements Hashable and Equatable, how does DifferenceKit decide if an item is an updated version of the same element, or an entirely different element at the same location?

Thanks,

  • Conrad

Hi @cnstoll
Sorry for late reply.

DifferenceKit determines whether the two elements are the same by the "hashValue" and the result of Equatable. == of differenceIdentifier.
And it compares whether it's an updated version by the result of Differentiable.isContentEqual(to:).
In other words, if the element itself or the value you want to get updates is differenceIdentifier, the algorithm considers all updates as deletes + inserts.

Failure case:

struct Element: Differentiable {
    var value: Int
    var flag: Bool

    var differenceIdentifier: Int {
        return value
    } 

    func isContentEqual(to source: Element) -> Bool {
        return value == source.value && flag == source.flag
    }
}

In this case, all the changes of element's value are regarded as deleted/inserted.

Success case:

enum ID {
    case foo, bar
}

struct Element: Differentiable {
    var id: ID
    var value: Int
    var flag: Bool

    var differenceIdentifier: ID {
        return id
    } 

    func isContentEqual(to source: Element) -> Bool {
        return value == source.value && flag == source.flag
    }
}

In this case, all the changes of element's value are regarded as updated correctly 🎉
If cases where your element has no suitable value as differenceIdentifier, you can use such as enum cases, Foundation.UUID, Int, String, etc.

Good luck.

I close this issue.
If you still want to ask, please reopen it.

@ra1028 I have tried your solution and the updates are still not being triggered.