I'm using NavigationSplitView
to structure the user interface of my (macOS) app like this:
struct NavigationView: View {
@State private var selectedApplication: Application?
var body: some View {
NavigationSplitView {
ApplicationsView(selectedApplication: $selectedApplication)
} detail: {
Text(selectedApplication?.name ?? "Nothing selected")
}
}
}
The sidebar is implemented using ApplicationsView
that looks like this:
struct ApplicationsView: View {
@FetchRequest(fetchRequest: Application.all()) private var applications
@Binding var selectedApplication: Application?
var body: some View {
List(applications, selection: $selectedApplication) { application in
NavigationLink(value: application) {
Text(application.name)
}
}
// This works, but looks a bit complicated and... ugly
.onReceive(applications.publisher) { _ in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
if selectedApplication == nil {
selectedApplication = applications.first
}
}
}
// This also does not work, as the data is not yet available
.onAppear {
selectedApplication = applications.first
}
}
}
I'm currently preselecting the first Application
item (if it exists) using the shown onReceive
code, but it looks complicated and a bit ugly. For example, it only works properly when delaying the selection code.
Is there a better way to achieve this?
Thanks.
How about just setting the
selectedApplication
using thetask
modifier with anid
as follows:the task is fired when the view is first displayed, and when the id object is updated, so this works without introducing a delay