Reputation: 311
The below 2 structs are the same with the exception of how they generate the identifier. Could you please explain what the difference is? If I use the first, my UICollectionViewDiffableDataSource works as expected (no scrolling on update). If I use the second, the diffable will scroll.
struct PostDetail {
var comment: Comment
var like: CommentLike?
var user: User
}
extension PostDetail: Hashable {
var identifier: UUID {
return UUID()
}
func hash(into hasher: inout Hasher) {
return hasher.combine(identifier)
}
public static func == (lhs: PostDetail, rhs: PostDetail) -> Bool {
return lhs.identifier == rhs.identifier
}
}
struct PostDetail {
let identifier = UUID()
var comment: Comment
var like: CommentLike?
var user: User
}
extension PostDetail: Hashable {
func hash(into hasher: inout Hasher) {
return hasher.combine(identifier)
}
public static func == (lhs: PostDetail, rhs: PostDetail) -> Bool {
return lhs.identifier == rhs.identifier
}
}
Upvotes: 0
Views: 74
Reputation: 535304
Just to expand on what I've said in my comment and Rob Napier has said in his answer:
In your first struct, identifier
is merely a function that generates a totally new value every time it is called. So it is never the same twice! Let's try it. Here's a reduced version of your struct:
struct PostDetail : Equatable {
var identifier: UUID {
return UUID()
}
static func ==(lhs:PostDetail, rhs:PostDetail) -> Bool {
lhs.identifier == rhs.identifier
}
}
Let's test it:
let p = PostDetail()
p.identifier // 3FFE9C66-5B80-4EF4-95EC-50388D35040B
p.identifier // 2D180097-CFAC-47E9-8530-C3BD3D39F433
So its "identifier" is not a constant; just the opposite, it is constantly changing. But you can't "identify" anything that way. Any attempt at defining Equatable based on that will fail, because no two PostDetail objects can ever be equal, even if they are the same object!
let p2 = PostDetail()
p2 == p2 // false
Similarly your Hashable will always fail, in the sense that no two PostDetail objects will fall into the same hash bucket, not even two instances of the same object.
To be an identifier, a UUID must be constant. In your second struct, we see this line:
let identifier = UUID()
That is a constant. It is generated when the instance is created and it never changes (because let
). That is how a UUID needs to behave.
So, you may seem to be working around some sort of animation "glitch", but you are doing so in a totally illegal and nonsensical way. There is no animation, I presume, because every PostDetail is "different" from every other, including itself. The entire diffable datasource content is being replaced, so there is nothing to animate (or something like that). You may be avoiding some interface behavior you don't like, but you are just fooling yourself, like someone who puts black tape over a car dashboard warning light.
Upvotes: 1
Reputation: 299345
The code in the first example is almost certainly wrong:
var identifier: UUID {
return UUID()
}
This creates a new identifier every time you access it, which is the opposite of "an identifier." The second example is correct.
Upvotes: 1