Ad

Save The Selection State Of The Current Selected Item On A List

- 1 answer

A macOS app that works with local files need to reload the files when it gets focused again. This is to load any new files that might have been placed there while the app was in the background.

The issue is that when I clear the list, reload the files (rebuilding the list), the first item is always selected, so if I was working on an item I'm being forced to select it again to continue working on it.

I tried keeping the current UUID of the selected note and passing that back, but I have no clue whether this is correct, or how to programmatically select an item in the list matching the UUID saved.

How do I keep the current selected item, and then go to it when I reload the data?

Code I tried:

struct DataItem: Codable, Hashable, Identifiable {
    let id: UUID
    var text: String
}

struct AllData: View {
    
    @EnvironmentObject private var data: DataModel //array of DataItem's    
    @State var selectedItemId: UUID?
    @State var currentItemId: UUID?
    
     NavigationView {
            List(data.prices.filter { searchText.isEmpty ? true : $0.text.localizedCaseInsensitiveContains(searchText) }) { price in
                NavigationLink(
                    destination: PriceView(price: price, text: price.text),
                    tag: price.id,
                    selection: $selectedItemId
                ) {
                    VStack(alignment: .leading) {
                        Text(getTitle(titleText: price.text)).font(.body).fontWeight(.bold)
                    }
                    .padding(.vertical, 10)
                }
            }

     }
    .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
            self.currentItemId = self.selectedItemId
            if getCurrentSaveDirectory(for: "savedDirectory") != "" {
                if !isDirectoryEmpty() {
                    data.price.removeAll()
                    loadFiles(dataModel: data)
                    self.selectedItemId = self.currentItemId
                }
            }
        }
}
Ad

Answer

I think using the current UUID of the selected note as you do is a good idea. Without all the code it is difficult to test my answer, however you could try this approach, using a Listselection variable and adding the simple code in onReceive, such as this example code:

struct AllData: View {
    
    @EnvironmentObject private var data: DataModel //array of DataItem's
    @State var selectedItemId: UUID?
    @State var currentItemId: UUID?
    
    @State var listSelection: DataItem?  // <--- here selection
    
    var body: some View {
        NavigationView {
            List(data.prices.filter { searchText.isEmpty ? true : $0.text.localizedCaseInsensitiveContains(searchText) },
                 selection: $listSelection) { price in  // <--- here selection
                NavigationLink(
                    destination: PriceView(price: price, text: price.text),
                    tag: price.id,
                    selection: $selectedItemId
                ) {
                    VStack(alignment: .leading) {
                        Text(getTitle(titleText: price.text)).font(.body).fontWeight(.bold)
                    }
                    .padding(.vertical, 10)
                }
            }
        }
        .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
            self.currentItemId = self.selectedItemId
            if getCurrentSaveDirectory(for: "savedDirectory") != "" {
                if !isDirectoryEmpty() {
                    data.price.removeAll()
                    loadFiles(dataModel: data)
                    self.selectedItemId = self.currentItemId
                    // --- here ---
                    if let theItem = data.first(where: {$0.id == selectedItemId}) {
                        listSelection = theItem
                    }
                }
            }
        }
    }
}
Ad
source: stackoverflow.com
Ad