Let’s say I have a model class Ball
, that conforms to the ObservableObject
protocol, and I define an optional instance of it (var ball: Ball?
).
Is there a way to trigger a NavigationLink
to display its destination
view based on setting the value of the optional instance? So when I self.ball = Ball()
, a NavigationLink
will trigger?
One problem seems to be that an optional (Type?
) can’t be an @ObservedObject
.
The other problem seems to be that the isActive:
parameter for NavigationLink
can only take a Binding<Bool>
.
/// Contrived minimal example to illustrate the problem.
include SwiftUI
class Ball: ObservableObject {
@Published var colour: String = "red"
// ...
}
struct ContentView: View {
// this won’t trigger view updates when it’s set because it’s not observed:
var ball: Ball?
// this line won’t compile:
@ObservedObject var observedBall: Ball?
// Property type 'Ball?' does not match that of the
// 'wrappedValue' property of its wrapper type 'ObservedObject'
var body: some View {
NavigationView {
VStack {
// I want this to navigate to the ballView when isActive becomes true,
// but it won’t accept the test of nil state on the optional value:
NavigationLink(
destination: BallView(ball: self.ball), isActive: self.ball != nil
) {
EmptyView()
} // compiler error because `self.ball != nil` isn’t valid for `isActive:`
// Button user taps to set the `ball`,
// which I want to trigger the BallView to be shown.
Button(action: { self.ball = Ball() }, label: { Text("Show Ball") })
}
}
}
}
struct BallView: View {
@ObservedObject var ball: Ball
// typical view stuff here ...
}
So far, the best workaround I have for the above limitations involves:
@State var ballIsSet = false
(or@Binding var ballIsSet: Bool
) variable to my view,didSet
function on the wrapped Ball variable that updates the passed in boolean.Phew!
Hopefully someone knows a simpler/better way to do this…