New to the forum and I hope this is an appropriate question.
To understand SwiftUI better under the hood, I am experimenting with passing around Bindings outside of Views. This is probably a bad idea. But I am hoping it throws some light on the lives of Binding variables and what happens to them in memory.
So today I tried to use a Binding as an associated value in an enum. The compiler tells me the resulting enum fails to conform to the Hashable and Equatable protocols. I believe it is because it is impossible for Binding to ever satisfy the needs of Hashable. But I'm not certain.
enum AppRoute: Equatable, Hashable {
case welcomeScreen
case slideshow(index: Binding<Int>)
static func ==(lhs: AppRoute, rhs: AppRoute) -> Bool {
// Some Equatable-conforming logic here to get at wrapped values
return lhs.hashValue == rhs.hashValue
// It seems like the tricky bit is that Binding cannot ever conform to Hashable. Or could it, with the right extension?
}
}
So is it impossible to pass SwiftUI bindings around, outside of relationships between Views? I am also wondering (hypothetically) if it might be possible using lower-level references like unsafe pointers.
I realize this is not the standard use case for @State and @Binding. Most likely this way lies madness. But basically I'm just curious about the survival of SwiftUI bindings outside of Views. And whether it is ever worth manipulating them from non-View classes.
sveinhal
(Svein Halvor Halvorsen)
2
Sure, pass them around. No problems. Embed them in enums with associated values, also no problem.
But you cannot, as you've found out, use them where some hashable value is expected.
1 Like
I am not entirely sure if this is good approach to conform Binding to Equatable and Hashable but this might work for you
extension Binding: Equatable where Value: Equatable {
public static func == (lhs: Binding<Value>, rhs: Binding<Value>) -> Bool {
lhs.wrappedValue == rhs.wrappedValue
}
}
extension Binding: Hashable where Value: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(self.wrappedValue)
}
}
enum AppRoute: Equatable, Hashable {
case welcomeScreen
case slideshow(index: Binding<Int>)
}