How to use NavigationSplitView instead of NavigationView where binding was used

It looks like passing a binding (instead of value) to a detail view is not possible with NavigationSplitView.

For example, how to adopt NavigationSplitView in sample app Date Planner — Sample Apps Tutorials | Apple Developer Documentation does not seem straight forward.

The only way seems to be to use ObservableObjects and use separate update methods on data.

...
    ForEach(eventData.sortedEvents(period: period)) { $event in
        NavigationLink {
            EventEditor(event: $event)
        } label: {
            EventRow(event: event)
        }

I was able to work around this by making a wrapper struct for the binding that conforms to Hashable if the value is Hashable.

Then I am able to do the following in the NavigationLink:

NavigationLink(value: HashableBindingWrapper<Event>(binding: $event) { … }

// Later in file:
.navigationDestination(for: HashableBindingWrapper<Event>.self) { wrapper in
    EventEditor(event: wrapper.binding)
}

It's ugly to need to do this instead of it being supported directly, but it seems to work. Thanks to Ben Scheirman for the suggestion.

Here's the code for HashableBindingWrapper:

struct HashableBindingWrapper<Value> {
    let binding: Binding<Value>
}

extension HashableBindingWrapper: Equatable where Value: Equatable {
    static func == (lhs: HashableBindingWrapper<Value>, rhs: HashableBindingWrapper<Value>) -> Bool {
        lhs.binding.wrappedValue == rhs.binding.wrappedValue
    }
}

extension HashableBindingWrapper: Hashable where Value: Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(binding.wrappedValue.hashValue)
    }
}
How to use NavigationSplitView instead of NavigationView where binding was used
 
 
Q