Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cells rendered incorrectly when using UITableView.reload(using:, with:) under certain contexts #99

Closed
3 tasks done
OliverPearmain opened this issue Mar 24, 2020 · 2 comments

Comments

@OliverPearmain
Copy link

Checklist

Given

An original list of three elements.

Component(title: "Shuffle Emojis", subtitle: "Shuffle sectioned Emojis in UICollectionView"),
Component(title: "Header Footer Section", subtitle: "Update header/footer by reload section in UITableView"),
Component(title: "Random", subtitle: "Random diff in UICollectionView")

If the list is updated so that the...

  • middle element is updated
  • first element is moved to the end

The resulting changeset will look like...

[
    Changeset(
        data: [
            Component(title: "Shuffle Emojis", subtitle: "Shuffle sectioned Emojis in UICollectionView"),
            Component(title: "Header Footer Section", subtitle: "XXX Update header/footer by reload section in UITableView"),
            Component(title: "Random", subtitle: "Random diff in UICollectionView")
        ],
        elementUpdated: [
            [element: 1, section: 0]
        ]
    ),
    Changeset(
        data: [
            Component(title: "Header Footer Section", subtitle: "XXX Update header/footer by reload section in UITableView"),
            Component(title: "Random", subtitle: "Random diff in UICollectionView"),
            Component(title: "Shuffle Emojis", subtitle: "Shuffle sectioned Emojis in UICollectionView")
        ],
        elementMoved: [
            (source: [element: 1, section: 0], target: [element: 0, section: 0]),
            (source: [element: 2, section: 0], target: [element: 1, section: 0])
        ]
    )
]

When

I apply this changeset to the UITableView with reload(using:, with:)...

Expected Behavior

The cells should animate appropriately and the cells should all be in their new positions with their updated values.

Current Behavior

Cells at index 0 and 1 are identical. Element 0 (originally 1) is not present in the UITableView.

Steps to Reproduce

I've modified the demo app in a fork to demonstrate the issue.

  1. Checkout https://github.com/OliverPearmain/DifferenceKit/tree/reload-with-move-bug
  2. Run the demo app
  3. The changeset will automatically be applied to the initial view contoller (so don't navigate anywhere, just watch the animation and resulting UITableView).

Detailed Description (Include Screenshots)

Please note that the "context" under which this happens is important because an identifcal changeset may not result in the same problem.

For instance, in the example code, if I rename the HomeViewController's components stored property to data then the problem goes away, WTF! The naming of properties should not affect the resulting animation, this is most peculiar. Demo code.

Reproducible Demo Project

https://github.com/OliverPearmain/DifferenceKit/tree/reload-with-move-bug

Environments

  • Library version: 1.1.5
  • Swift version: Swift 5
  • iOS version: 13.3
  • Xcode version: 11.3.1
  • Devices/Simulators: iPhone 11 - 13.3 Simulator
  • CocoaPods/Carthage version: n/a
@ra1028
Copy link
Owner

ra1028 commented Mar 31, 2020

@OliverPearmain

I checked your demo.
You seem to be using reload(using:with:) method incorrectly.
DifferenceKit applies the diffs in several stages, so you should set the data that passed to the setData closure to var components, like below.

let components = [
    Component(title: "Header Footer Section", subtitle: "XXX Update header/footer by reload section in UITableView"),
    Component(title: "Random", subtitle: "Random diff in UICollectionView"),
    Component(title: "Shuffle Emojis", subtitle: "Shuffle sectioned Emojis in UICollectionView"),
]
     
let changeset = StagedChangeset(source: self.components, target: components)
tableView.reload(using: changeset, with: .fade) { data in
    self.components = data
}

@OliverPearmain
Copy link
Author

Aha, bingo. 🤦‍♂ Thanks so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants