Listで選択された要素の取得
List(_:selection:) + Identifiable.ID を使う
|
1 2 3 4 5 |
@State private var selectedID: ScreenshotItem.ID? List(items, selection: $selectedID) { item in Text("item") } |
モデル
|
1 2 3 4 |
struct ScreenshotItem: Identifiable, Hashable { let id = UUID() let cgImage: CGImage } |
View
|
1 2 3 4 5 6 7 8 9 10 |
@State private var screenshots: [ScreenshotItem] = [] @State private var selectedID: ScreenshotItem.ID? List(screenshots, selection: $selectedID) { item in Image(decorative: item.cgImage, scale: 2.0) .resizable() .scaledToFit() .frame(height: 80) } .listStyle(.sidebar) |
選択された「実体」を取得
|
1 2 3 |
var selectedItem: ScreenshotItem? { screenshots.first { $0.id == selectedID } } |
複数選択の場合
|
1 2 3 4 5 |
@State private var selection = Set<ScreenshotItem.ID>() List(screenshots, selection: $selection) { item in Text("SS") } |
実体取得
|
1 2 3 |
let selectedItems = screenshots.filter { selection.contains($0.id) } |
「クリック時に即処理したい」場合
onChange を使う
|
1 2 3 4 5 |
.onChange(of: selectedID) { _, newValue in guard let id = newValue else { return } let item = screenshots.first { $0.id == id } // メインに反映、加工開始など } |
選択された要素の削除の例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Button(action: { guard let id = selected_item else { return } // 選択されている要素を削除 SS_images.removeAll { $0.id == id } // 選択状態をクリア selected_item = nil image = nil }) { Image(systemName: "trash.circle") .resizable() .foregroundColor(Color(.blue)) .frame(width: 20, height: 20) } |
複数選択にする例
複数選択を有効にするには、Listに.selectionDisabled(false)を追加するだけでは不十分です。以下の修正が必要です:
修正箇所
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
struct ScreenshotSidebarView: View { @Binding var capture_image: CGImage? @Binding var SS_images: [ScreenshotItem] @Binding var selected_item: Set<ScreenshotItem.ID> // ← ? を削除(常にSetを持つ) @State private var trash_flg: Bool = false var selected_image: CGImage? { guard let firstID = selected_item.first else { return nil } // ← selected_itemは常にSetなので guard let 不要 return SS_images.first { $0.id == firstID }?.cg_image } var multiple_selected_image: [ScreenshotItem] { return SS_images.filter { selected_item.contains($0.id) } // ← シンプルに } var body: some View { HStack { List(SS_images, selection: $selected_item) { item in Image(decorative: item.cg_image, scale: 2.0) .resizable() .scaledToFit() .frame(height: 80) .padding(4) } .listStyle(.sidebar) // ← ここに何も追加しなくてOK |
重要なポイント
@Binding var selected_item: Set<ScreenshotItem.ID>- macOSでは自動的に複数選択が有効
ScreenshotItemがIdentifiableに準拠している必要がある
|
1 2 3 4 5 |
struct ScreenshotItem: Identifiable { let id: UUID let cg_image: CGImage // ... } |
親ビューでの使い方
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
struct ParentView: View { @State private var SS_images: [ScreenshotItem] = [] @State private var selected_item: Set<ScreenshotItem.ID> = [] // ← 空のSetで初期化 @State private var capture_image: CGImage? var body: some View { ScreenshotSidebarView( capture_image: $capture_image, SS_images: $SS_images, selected_item: $selected_item ) } } |
選択状態の確認
|
1 2 3 4 5 6 7 |
// 選択数を表示 Text("選択数: \(selected_item.count)") // 選択されているか確認 if !selected_item.isEmpty { Text("選択中") } |
これでCommandキーやShiftキーを使った複数選択ができるようになります!試してみてください。
コメント