1

アイテムを追加できるリストがあり、それらをクリックすると正しい詳細ビューが開きました。最近リストを LazyVGrid に交換しましたが、グリッド項目をクリックすると、詳細ビ​​ューは配列の最初の項目のみを呼び出します。

これはリスト ビューです。

import SwiftUI

struct ListView: View {

    @EnvironmentObject var listViewModel: ListViewModel
    @State var addItemView = false
    @State var detailView = false
    
    let columns = [GridItem(.flexible()), GridItem(.flexible())]

    var body: some View {
        NavigationView {
            ZStack {
                ZStack {
                    Color(.white)
                }
                VStack {
                    Button(action: {
                        self.addItemView = true
                    }, label: {
                        Text("Add")
                    }).sheet(isPresented: $addItemView, content: {
                        AddItemView()
                    })
                    LazyVGrid(columns: columns, spacing: 20) {  // <-- the only line i comment when using list
//                        List {
                        ForEach(listViewModel.item, id:\.id){ item in
                            Button(action: {
                                self.detailView = true
                            }, label: {
                                ListRowView(item: item)
                            }).sheet(isPresented: $detailView, content: {
                                DetailView(item: item)
                            })
                        }
//                            .onDelete(perform: listViewModel.deleteItem)
//                            .onMove(perform: listViewModel.moveItem)
//                            .listRowBackground(Color.blue)
                    }
//                        .listStyle(PlainListStyle())
                    Spacer()
                }
            }
        }
    }
}

struct ListRowView: View {   // <-- using this as grid item
    @State var item:Item

    var body: some View{
        VStack {
            Text(item.name).foregroundColor(.white)
        }.frame(width: 150, height: 150, alignment: .center)
        .background(Color.blue)
        .cornerRadius(10)
    }
}

アイテムの追加と詳細ビュー:

struct AddItemView: View {
    @Environment(\.presentationMode) var presentationMode
    @EnvironmentObject var listViewModel: ListViewModel
    @State var id = UUID()
    @State var name = ""

    var body: some View {
        TextField("Enter Name", text: $name)
        Button(action: {
            addItem()
        }, label: {
            Text("Done")
        })
    }

    func addItem() {
        listViewModel.addItem(id: id.uuidString, name: name)
        presentationMode.wrappedValue.dismiss()
    }
}

struct DetailView: View {
    @State var item:Item

    var body: some View {
        Text(item.name)
    }
}

そして、これが各アイテムを追加する方法です:

import Foundation

struct Item: Hashable, Codable, Equatable {
    var id:String
    var name: String
}

class ListViewModel: ObservableObject {

    @Published var item: [Item] = [] {
        didSet {
            saveItem()
        }
    }

    let itemsKey: String = "items_key"

    init() {
        getItems()
    }

    func getItems() {
        guard
            let data = UserDefaults.standard.data(forKey: itemsKey),
            let savedItems = try? JSONDecoder().decode([Item].self, from: data)
        else { return }
    
        self.item = savedItems
    }

    func deleteItem(indexSet: IndexSet){
        item.remove(atOffsets: indexSet)
    }

    func moveItem(from: IndexSet, to: Int){
        item.move(fromOffsets: from, toOffset: to)
    }

    func addItem(id: String, name: String){
        let newItem = Item(id: id, name: name)
        item.append(newItem)
        print(newItem)
    }

    func saveItem() {
        if let encodedData = try? JSONEncoder().encode(item) {
            UserDefaults.standard.set(encodedData, forKey: itemsKey)
        }
    }
}

LazyVGrid が最初のアイテムのみを呼び出している理由がわかりません。

4

1 に答える 1