NavigationSplitView
does not run .task
for each detail
view instance. I'm trying to update my code from NavigationView
to NavigationSplitView.
I was having trouble, since I rely upon .task
to update the @State
of my detail
view. It does not update this state in the detail view when using NavigationSplitView.
Please see my comments in the code snippet below. Does anyone have any suggestions? FWIW I have also filed FB11932889.
Thanks for any help.
import SwiftUI
enum Category: CaseIterable, Hashable {
case first
case second
}
struct CategoryRow: View {
let category: Category
var body: some View {
Text("Row: \(String(describing: category))")
}
}
struct CategoryDetail: View {
enum LoadingState {
case none
case loading
case loaded
case error
}
let category: Category
@State private var loadingState: LoadingState = .none
var body: some View {
VStack {
Text("Category: \(String(describing: category))")
Text("LoadingState: \(String(describing: loadingState))")
}
.task {
// If this .task does not run ever, the view will show a .none Category.
// If this .task runs, the view will start by showing .loading, and then .loaded
// The bug found when this is in CategoryNavigationSplitView that: this .task does not run for the .second category,
// but the @State is not reset, it will show .loaded for the second category chosen!
// I expect this .task to run each time, and not carry over the @State from
// previous CategoryDetail. It must be a new CategoryDetail View, since the
// let Category constant is changing.
// When this is in CategoryNavigationView, the .task runs as expected.
loadingState = .loading
do {
try await Task.sleep(for: .seconds(2))
loadingState = .loaded
} catch {
loadingState = .error
}
}
}
}
struct CategoryNavigationSplitView: View {
@State var selectedCategory: Category?
var body: some View {
NavigationSplitView {
List(Category.allCases, id: \.self, selection: $selectedCategory) { category in
NavigationLink(value: category) { CategoryRow(category: category) }
}
} detail: {
if let selectedCategory {
CategoryDetail(category: selectedCategory)
} else {
Text("Select a Category")
}
}
}
}
struct CategoryNavigationView: View {
@State var selectedCategory: Category?
var body: some View {
NavigationView {
List(Category.allCases, id: \.self, selection: $selectedCategory) { category in
NavigationLink {
CategoryDetail(category: category)
} label: {
CategoryRow(category: category)
}
}
}
Text("Select a Category")
}
}