When using NavigationLink or presentation link in swiftUI, the navigation controller doesn't push or present a new View, getting error
"[WindowServer] display_timer_callback: unexpected state"
ForEach(self.items.identified(by: \.name)) { item in
NavigationLink(destination: Text("DT In the House")) {
CategoryItem(item: item)
}
}
[] nw_connection_receive_internal_block_invoke [C4] Receive reply failed with error "Operation canceled"
A navigation view style represented by a view stack that only shows a single top view at a time.
isDetailLink. A Boolean value that specifies whether this link presents its destination as the detail component when used in a multi-column navigation view.
I believe this is bug in PresentationLink in current SwiftUI beta. I get the same error while trying to reopen modal after dismissing it.
EDIT1:
NavigationLink requires to be embedded in NavigationView and if there is none will present message [WindowServer] display_timer_callback: unexpected state (now:1abc3d3ccc7 < expected:1abc3d91a0f)
EDIT2: PresentationLink only appears to be buggy while embedded in things like NavigationBarItems or Lists etc.
It seems to be a bug. I've managed to whip up a (dirty) workaround:
private enum SetPresentedViewKey: EnvironmentKey {
static var defaultValue: (AnyView?) -> () {
fatalError()
}
}
private extension EnvironmentValues {
var setPresentedView: (AnyView?) -> () {
get {
self[SetPresentedViewKey.self]
} set {
self[SetPresentedViewKey.self] = newValue
}
}
}
/// A replacement for the buggy (as of Xcode 11 b3) `PresentationLink`.
public struct PresentationLink2<Destination: View, Label: View>: View {
public let destination: Destination
public let label: Label
@Environment(\.setPresentedView) private var setPresentedView
@State private var presentedView: AnyView? = nil
public init(destination: Destination, @ViewBuilder _ label: () -> Label) {
self.destination = destination
self.label = label()
}
private struct _Body<Destination: View, Label: View>: View {
@Environment(\.setPresentedView) private var setPresentedView
let destination: Destination
let label: Label
init(destination: Destination, label: Label) {
self.destination = destination
self.label = label
}
var body: some View {
Button(action: present, label: { label })
}
func present() {
setPresentedView(AnyView(destination))
}
}
public var body: some View {
_Body(destination: destination, label: label)
.environment(\.setPresentedView, { self.presentedView = $0 })
.presentation(presentedView.map {
Modal($0, onDismiss: { self.presentedView = nil })
})
}
}
Just copy the code above into your codebase and use PresentationLink2
instead of PresentationLink
.
As noted by @kozlowsqi, PresentationLink
seems to be broken when embedded in a NavigationView
. What's alarming is that it's still broken as of Xcode beta 3.
Edit: I've filed a radar through the new Feedback Assistant app, FB6525020. Please raise your own and reference mine, and hopefully this will be resolved by beta 4.
I've created a PresentationLink replacement that works far more reliable. Hopefully it won't be needed anymore as soon as beta 4 is released.
You can find a gist here: https://gist.github.com/petercv/3fba967a69b262901053fc8638b7851b
I've also added support for a .isModalInPresentation(_ value: Bool) modifier to set the isModalInPresentation property of UIViewController. Hopefully Apple will add this too soon.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With