admin管理员组

文章数量:1122832

In the below code I cannot select any of my list items:

import SwiftUI
import SwiftData

struct ItemView: View {
    
    @Environment(\.modelContext) private var context
    @Query(sort: \Item.title) private var items: [Item]
    
    @State private var selection: String? = nil
    
    var body: some View {
        if items.isEmpty {
            ContentUnavailableView("Enter your first item.", systemImage: "bookmark.fill")
        } else {
            List(items, id: \.self, selection: $selection) { item in
                Text(item.title)
            }
        }
    }
}

However in a very similar example that uses an array for my list items rather than a DB I can select items:

import SwiftUI

struct ContentView: View {
    @State private var selection: String?
    @State private var isOn: Bool = false
    
    let names = [
        "Cyril",
        "Lana",
        "Mallory",
        "Sterling"
    ]

    var body: some View {
        NavigationStack {
            List(names, id: \.self, selection: $selection) { name in
                Toggle(isOn: $isOn) {
                    Text(name)
                }
            }
            .navigationTitle("List Selection")
            .toolbar {
                
            }
        }
    }
}

My console log shows:

Can't find or decode reasons
Failed to get or decode unavailable reasons
NSBundle file:///System/Library/PrivateFrameworks/MetalTools.framework/ principal class is nil because all fallbacks have failed

What am I doing wrong?

In the below code I cannot select any of my list items:

import SwiftUI
import SwiftData

struct ItemView: View {
    
    @Environment(\.modelContext) private var context
    @Query(sort: \Item.title) private var items: [Item]
    
    @State private var selection: String? = nil
    
    var body: some View {
        if items.isEmpty {
            ContentUnavailableView("Enter your first item.", systemImage: "bookmark.fill")
        } else {
            List(items, id: \.self, selection: $selection) { item in
                Text(item.title)
            }
        }
    }
}

However in a very similar example that uses an array for my list items rather than a DB I can select items:

import SwiftUI

struct ContentView: View {
    @State private var selection: String?
    @State private var isOn: Bool = false
    
    let names = [
        "Cyril",
        "Lana",
        "Mallory",
        "Sterling"
    ]

    var body: some View {
        NavigationStack {
            List(names, id: \.self, selection: $selection) { name in
                Toggle(isOn: $isOn) {
                    Text(name)
                }
            }
            .navigationTitle("List Selection")
            .toolbar {
                
            }
        }
    }
}

My console log shows:

Can't find or decode reasons
Failed to get or decode unavailable reasons
NSBundle file:///System/Library/PrivateFrameworks/MetalTools.framework/ principal class is nil because all fallbacks have failed

What am I doing wrong?

Share Improve this question asked Nov 23, 2024 at 3:15 ianian 12.3k26 gold badges71 silver badges96 bronze badges 1
  • id: \.self is usually wrong – malhal Commented Nov 23, 2024 at 18:11
Add a comment  | 

1 Answer 1

Reset to default 0

The reason you don't get a selection is because you are missing the .tag(...).

When you use the array names, it is provided for you, but not when you use the items: [Item] (the types don't match).

Example code:

 struct ContentView: View {
     
     @Environment(\.modelContext) private var context
     @Query(sort: \Item.title) private var items: [Item]
     
     @State private var selection: String? 
     
     var body: some View {
         Text(selection ?? "no selection")
         if items.isEmpty {
             ContentUnavailableView("Enter your first item.", systemImage: "bookmark.fill")
         } else {
             List(items, selection: $selection) { item in
                 Text(item.title)
                     .tag(item.title)  // <--- here
             }
         }
     }
 }

Note, using selection: String? is not a great idea, try using selection: PersistentIdentifier? and use .tag(item.id) instead. The tag must match the type of the selection exactly.

You could of course also use @State private var selection: Item? with .tag(item).

struct ContentView: View {
    
    @Environment(\.modelContext) private var context
    @Query(sort: \Item.title) private var items: [Item]
    
    @State private var selection: Item? // <--- here
    
    var body: some View {
        Text(selection?.title ?? "no selection") // <--- for testing
        if items.isEmpty {
            ContentUnavailableView("Enter your first item.", systemImage: "bookmark.fill")
        } else {
            List(items, selection: $selection) { item in
                Text(item.title)
                    .tag(item)  // <--- here
            }
        }
    }
}

Note also, do not use List(items, id: \.self, ..., let the Item id do the job as shown in the example code.

本文标签: macosWhy doesn39t list selection work when my list is from a DBStack Overflow