I am trying to understand @State. Ignoring the view model in the picture, I am trying to present a view modally with sheet modifier on tapping any item on my lazygrid. For some reason an empty view is presented as the selected item is always nil for some reason.
This is how my state properties looks
@State private var selectedFollower : Follower? = nil
@State var showFollowerDetail = false
This is the presentation on list
ForEach(followers, id: \.self) { follower in
GridCells(follower: follower)
.onTapGesture {
selectedFollower = follower
showFollowerDetail = true
}
}
And this is the sheet modifier
.sheet(isPresented: $showFollowerDetail, content: {
if let selectedFollower{
UserInfoView(follower: selectedFollower)
}
})
(Although it seems like an internal bug to me), it happens when you try to define a separate flag State
and manually manage it and sometimes it gets out of sync somehow (like when there is a race between the render engine and the closure capture).
To work around it, you can drive the Binding<Bool>
directly from the source of truth to make sure it is always in sync:
@State private var selectedFollower: Follower?
var showFollowerDetail: Binding<Bool> {
.init {
selectedFollower != nil
} set: {
guard !$0 else { return }
selectedFollower = nil
}
}
Or simply use the other initializer that accepts an optional as recommended:
.sheet(item: $selectedFollower) { selectedFollower in
UserInfoView(follower: selectedFollower)
}