最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swiftui - Preselection of list in NavigationSplitView with SceneStorage - Stack Overflow

programmeradmin2浏览0评论

I've got a list in sidebar of NavigationSplitView. The view in detail should change by selecting an item. For restoration of view I'm using SceneStorage like this:

import SwiftUI

enum ListType: String {
   case all = "all"
   case frequently = "frequently"
}

struct MyListItem: Identifiable, Hashable {
   let type: ListType
   let label: String
   let id = UUID()
}

struct SelectionMode: View {
   
   @State private var listItems = [
      MyListItem(type: .all, label: "alle Unterrichte"),
      MyListItem(type: .frequently, label: "am häufigsten")
   ]

   @SceneStorage("ListType") private var selectedType: ListType?

   var body: some View {
    
      NavigationSplitView {
        List(listItems, id: \.self.type, selection: $selectedType) { type in
            NavigationLink("\(type.label)", value: type)
        }
      } detail: {
        NavigationStack {
            SelectedList(viewType: selectedType?.rawValue ?? "all")
        }
    }
}

This works well, with one exception: The selected item is not highlighted in the list. First, “all” should be highlighted or the selected item (e.g. “frequently”) after the restoration. How can I achieve this?

I've got a list in sidebar of NavigationSplitView. The view in detail should change by selecting an item. For restoration of view I'm using SceneStorage like this:

import SwiftUI

enum ListType: String {
   case all = "all"
   case frequently = "frequently"
}

struct MyListItem: Identifiable, Hashable {
   let type: ListType
   let label: String
   let id = UUID()
}

struct SelectionMode: View {
   
   @State private var listItems = [
      MyListItem(type: .all, label: "alle Unterrichte"),
      MyListItem(type: .frequently, label: "am häufigsten")
   ]

   @SceneStorage("ListType") private var selectedType: ListType?

   var body: some View {
    
      NavigationSplitView {
        List(listItems, id: \.self.type, selection: $selectedType) { type in
            NavigationLink("\(type.label)", value: type)
        }
      } detail: {
        NavigationStack {
            SelectedList(viewType: selectedType?.rawValue ?? "all")
        }
    }
}

This works well, with one exception: The selected item is not highlighted in the list. First, “all” should be highlighted or the selected item (e.g. “frequently”) after the restoration. How can I achieve this?

Share Improve this question asked Mar 27 at 21:47 user2836375user2836375 1392 silver badges11 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Try this approach using a @State private var selectedItem: MyListItem? to do the List selection, as it matches the List display MyListItem type set with .tag(item).


struct ContentView: View {
    var body: some View {
        SelectionMode()
    }
}

enum ListType: String {
    case all = "all"
    case frequently = "frequently"
}

struct MyListItem: Identifiable, Hashable {
   let type: ListType
   let label: String
   let id = UUID()
}

struct SelectionMode: View {
    
    @State private var listItems = [
        MyListItem(type: .all, label: "alle Unterrichte"),
        MyListItem(type: .frequently, label: "am häufigsten")
    ]
    
    // only for scenes (screens), will be lost when App is closed
 //   @SceneStorage("ListType") private var selectedType: ListType?
    
    // for the whole App, for my testing, keeps the storage after App is closed
    @AppStorage("ListType") private var selectedType: ListType?
    
    @State private var selectedItem: MyListItem?  // <--- here
    
    var body: some View {
        NavigationSplitView {
            List(listItems, selection: $selectedItem) { item in
                Text(item.label).tag(item) // <--- here
            }
        } detail: {
            NavigationStack {
                if let selectedItem = selectedItem {
                    SelectedList(viewType: selectedItem.type.rawValue)
                } else {
                    Text("Select an item").font(.title)
                }
            }
        }
        .onAppear {
            if selectedType == nil {
                selectedType = .all
            }
            if let index = listItems.firstIndex(where: {$0.type == selectedType!}) {
                selectedItem = listItems[index] // <--- here
            }
        }
        .onChange(of: selectedItem) {
            selectedType = selectedItem?.type  // <--- here
        }
    }
}

struct SelectedList: View {
    let viewType: String
    
    var body: some View {
        Text("Selected type: \(viewType)").font(.title)
    }
}

发布评论

评论列表(0)

  1. 暂无评论