【SwiftUI】PhotosPickerで選んだ画像をハイライト表示&高画質プレビューする

## はじめに

SwiftUIで画像ライブラリを表示しつつ、PhotosPickerで選んだ画像をハイライト表示&高画質プレビューするUI実装をまとめています。

## 実装イメージ

- サムネイル一覧を表示（複数選択可能）
- 選択された画像には白いハイライトを表示
- タップで高画質プレビュー画面に遷移（`fullScreenCover`）

## 使用環境

- Swift 6.1
- Xcode 16.2
- SwiftUI

---

## コード

```swift
import SwiftUI
import PhotosUI

struct ImageGalleryView: View {
    // PhotosPickerで選択された画像のメタ情報
    @State private var selectedItems: [PhotosPickerItem] = []
    // 実際に表示するUIImageの配列
    @State private var images: [UIImage] = []
    // 現在選択中のインデックス
    @State private var selectedIndex: Int? = nil
    // プレビュー画面の表示フラグ
    @State private var isPreviewPresented = false

    var body: some View {
        NavigationView {
            VStack {
                // 写真選択ボタン（最大10枚）
                PhotosPicker(selection: $selectedItems,
                             maxSelectionCount: 10,
                             matching: .images,
                             photoLibrary: .shared()) {
                    Text("画像選択")
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(8)
                }

                // 選択された画像の一覧表示（グリッド）
                ScrollView {
                    LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))], spacing: 10) {
                        ForEach(images.indices, id: \.self) { index in
                            Image(uiImage: images[index])
                                .resizable()
                                .scaledToFill()
                                .frame(width: 100, height: 100)
                                .clipped()
                                // 選択状態を白くハイライト表示
                                .overlay(
                                    RoundedRectangle(cornerRadius: 8)
                                        .fill(Color.white.opacity(selectedIndex == index ? 0.4 : 0.0))
                                )
                                // タップでプレビュー表示へ
                                .onTapGesture {
                                    selectedIndex = index
                                    isPreviewPresented = true
                                }
                        }
                    }
                    .padding()
                }
            }
            .navigationTitle("画像ライブラリ")
        }
        // 選択項目が変更されたときに画像データを読み込み
        .onChange(of: selectedItems) {
            Task {
                images = [] // 初期化
                for item in selectedItems {
                    // Dataとして読み込み → UIImageに変換
                    if let data = try? await item.loadTransferable(type: Data.self),
                       let image = UIImage(data: data) {
                        images.append(image)
                    }
                }
            }
        }
        // フルスクリーンでの画像プレビュー
        .fullScreenCover(isPresented: $isPreviewPresented) {
            if let index = selectedIndex, images.indices.contains(index) {
                ZStack {
                    Color.black.ignoresSafeArea()
                    Image(uiImage: images[index])
                        .resizable()
                        .scaledToFit()
                        .padding()
                }
                // タップで閉じる
                .onTapGesture {
                    isPreviewPresented = false
                }
            }
        }
    }
}

```

## まとめ

SwiftUIの PhotosPicker と組み合わせることで、写真選択・非同期ローディング・UI表現をシンプルに実装できます。特に以下の点が良い学びになりました。
- 状態管理（@State）とイベント駆動の連携方法
- 非同期で複数画像を処理するシンプルな書き方
- overlay による視覚表現の柔軟性