質問編集履歴
3
修正版コードを追記しました。
    
        title	
    CHANGED
    
    | 
            File without changes
         | 
    
        body	
    CHANGED
    
    | @@ -262,7 +262,7 @@ | |
| 262 262 | 
             
            //  ItemService.swift
         | 
| 263 263 | 
             
            import Foundation
         | 
| 264 264 | 
             
            struct ItemService {
         | 
| 265 | 
            -
                func readItems(completion: @escaping([Item]) -> Void) {
         | 
| 265 | 
            +
                func readItems(gearList:GearList, completion: @escaping([Item]) -> Void) {
         | 
| 266 266 | 
             
                    let items: [Item] = [
         | 
| 267 267 | 
             
                        Item(brandid: "brandid",
         | 
| 268 268 | 
             
                             brandname: "brandname",
         | 
| @@ -294,6 +294,7 @@ | |
| 294 294 | 
             
            //  ListViewModel.swift
         | 
| 295 295 | 
             
            import Foundation
         | 
| 296 296 | 
             
            import Observation
         | 
| 297 | 
            +
             | 
| 297 298 | 
             
            @Observable class ListViewModel {
         | 
| 298 299 | 
             
                private let itemservice = ItemService()
         | 
| 299 300 | 
             
                private var gearList : GearList
         | 
| @@ -304,11 +305,11 @@ | |
| 304 305 | 
             
                }
         | 
| 305 306 | 
             
                init(gearList:GearList) {
         | 
| 306 307 | 
             
                    self.gearList = gearList
         | 
| 307 | 
            -
                    readAndSortItems()
         | 
| 308 | 
            +
                    readAndSortItems(gearList:gearList)
         | 
| 308 309 | 
             
                }
         | 
| 309 | 
            -
                func readAndSortItems() -> Void {
         | 
| 310 | 
            +
                func readAndSortItems(gearList:GearList) -> Void {
         | 
| 310 311 | 
             
                    listData = []
         | 
| 311 | 
            -
                    itemservice.readItems() { item in
         | 
| 312 | 
            +
                    itemservice.readItems(gearList:gearList) { item in
         | 
| 312 313 | 
             
                        print("completion")
         | 
| 313 314 | 
             
                        self.listData.append(item)
         | 
| 314 315 | 
             
                    }
         | 
| @@ -341,7 +342,7 @@ | |
| 341 342 | 
             
                    }
         | 
| 342 343 | 
             
                }
         | 
| 343 344 | 
             
                func action() {
         | 
| 344 | 
            -
                    listVM.readAndSortItems()
         | 
| 345 | 
            +
                    listVM.readAndSortItems(gearList: gearList)
         | 
| 345 346 | 
             
                }
         | 
| 346 347 | 
             
            }
         | 
| 347 348 |  | 
2
Firestore記述を削除したコード全体を追記しました。
    
        title	
    CHANGED
    
    | 
            File without changes
         | 
    
        body	
    CHANGED
    
    | @@ -198,8 +198,156 @@ | |
| 198 198 | 
             
            }
         | 
| 199 199 |  | 
| 200 200 | 
             
            ```
         | 
| 201 | 
            +
            ### 追記:Firestore記述を削除したコード全体
         | 
| 202 | 
            +
            ```code全体(修正版)
         | 
| 201 203 |  | 
| 204 | 
            +
            //  ContentView.swift
         | 
| 205 | 
            +
            import SwiftUI
         | 
| 206 | 
            +
            struct ContentView: View {
         | 
| 207 | 
            +
                let gearList =
         | 
| 208 | 
            +
                GearList(
         | 
| 209 | 
            +
                    gearlistid: "gearlistid",
         | 
| 210 | 
            +
                    listname: "gearlistname",
         | 
| 211 | 
            +
                    lengthofstay: "2day",
         | 
| 212 | 
            +
                    howtostay: "Hotel",
         | 
| 213 | 
            +
                    startdate: Date(),
         | 
| 214 | 
            +
                    baseweight: 100,
         | 
| 215 | 
            +
                    consumableweight: 100,
         | 
| 216 | 
            +
                    wornweight: 100,
         | 
| 217 | 
            +
                    totalweight: 300
         | 
| 218 | 
            +
                )
         | 
| 219 | 
            +
                var body: some View {
         | 
| 220 | 
            +
                    ListView(gearList: gearList)
         | 
| 221 | 
            +
                }
         | 
| 222 | 
            +
            }
         | 
| 202 223 |  | 
| 224 | 
            +
            #Preview {
         | 
| 225 | 
            +
                ContentView()
         | 
| 226 | 
            +
            }
         | 
| 227 | 
            +
             | 
| 228 | 
            +
             | 
| 229 | 
            +
            //  Item.swift
         | 
| 230 | 
            +
            import Foundation
         | 
| 231 | 
            +
            struct Item: Codable, Identifiable, Hashable {
         | 
| 232 | 
            +
                var id: String?
         | 
| 233 | 
            +
                var brandid: String
         | 
| 234 | 
            +
                var brandname: String
         | 
| 235 | 
            +
                var categoryid: Int
         | 
| 236 | 
            +
                var categoryname: String
         | 
| 237 | 
            +
                var createdAt: Date
         | 
| 238 | 
            +
                var itemid: String
         | 
| 239 | 
            +
                var memo: String
         | 
| 240 | 
            +
                var name: String
         | 
| 241 | 
            +
                var subcategoryid: Int
         | 
| 242 | 
            +
                var subcategoryname: String
         | 
| 243 | 
            +
                var updatedAt: Date
         | 
| 244 | 
            +
            }
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            //  GearList.swift
         | 
| 247 | 
            +
            import Foundation
         | 
| 248 | 
            +
            struct GearList: Codable, Identifiable, Hashable {
         | 
| 249 | 
            +
                var id: String?
         | 
| 250 | 
            +
                var gearlistid : String
         | 
| 251 | 
            +
                var listname : String
         | 
| 252 | 
            +
                var lengthofstay : String
         | 
| 253 | 
            +
                var howtostay : String
         | 
| 254 | 
            +
                var startdate : Date
         | 
| 255 | 
            +
                var baseweight : Int
         | 
| 256 | 
            +
                var consumableweight : Int
         | 
| 257 | 
            +
                var wornweight : Int
         | 
| 258 | 
            +
                var totalweight : Int
         | 
| 259 | 
            +
            }
         | 
| 260 | 
            +
             | 
| 261 | 
            +
             | 
| 262 | 
            +
            //  ItemService.swift
         | 
| 263 | 
            +
            import Foundation
         | 
| 264 | 
            +
            struct ItemService {
         | 
| 265 | 
            +
                func readItems(completion: @escaping([Item]) -> Void) {
         | 
| 266 | 
            +
                    let items: [Item] = [
         | 
| 267 | 
            +
                        Item(brandid: "brandid",
         | 
| 268 | 
            +
                             brandname: "brandname",
         | 
| 269 | 
            +
                             categoryid: 11,
         | 
| 270 | 
            +
                             categoryname: "categoryname",
         | 
| 271 | 
            +
                             createdAt: Date(),
         | 
| 272 | 
            +
                             itemid: "itemid",
         | 
| 273 | 
            +
                             memo: "memo",
         | 
| 274 | 
            +
                             name: "name\(Int.random(in: 0..<100))",
         | 
| 275 | 
            +
                             subcategoryid: 12,
         | 
| 276 | 
            +
                             subcategoryname: "subcategoryname",
         | 
| 277 | 
            +
                             updatedAt: Date()),
         | 
| 278 | 
            +
                        Item(brandid: "brandid",
         | 
| 279 | 
            +
                             brandname: "brandname",
         | 
| 280 | 
            +
                             categoryid: 11,
         | 
| 281 | 
            +
                             categoryname: "categoryname",
         | 
| 282 | 
            +
                             createdAt: Date(),
         | 
| 283 | 
            +
                             itemid: "itemid",
         | 
| 284 | 
            +
                             memo: "memo",
         | 
| 285 | 
            +
                             name: "name\(Int.random(in: 0..<100))",
         | 
| 286 | 
            +
                             subcategoryid: 12,
         | 
| 287 | 
            +
                             subcategoryname: "subcategoryname",
         | 
| 288 | 
            +
                             updatedAt: Date()),
         | 
| 289 | 
            +
                    ]
         | 
| 290 | 
            +
                    completion(items)
         | 
| 291 | 
            +
                }
         | 
| 292 | 
            +
            }
         | 
| 293 | 
            +
             | 
| 294 | 
            +
            //  ListViewModel.swift
         | 
| 295 | 
            +
            import Foundation
         | 
| 296 | 
            +
            import Observation
         | 
| 297 | 
            +
            @Observable class ListViewModel {
         | 
| 298 | 
            +
                private let itemservice = ItemService()
         | 
| 299 | 
            +
                private var gearList : GearList
         | 
| 300 | 
            +
                var listData: [[Item]] = []
         | 
| 301 | 
            +
                init() {
         | 
| 302 | 
            +
                    print("init")
         | 
| 303 | 
            +
                    self.gearList = GearList(gearlistid: "", listname: "", lengthofstay: "", howtostay: "", startdate: Date(), baseweight: 0, consumableweight: 0, wornweight: 0, totalweight: 0)
         | 
| 304 | 
            +
                }
         | 
| 305 | 
            +
                init(gearList:GearList) {
         | 
| 306 | 
            +
                    self.gearList = gearList
         | 
| 307 | 
            +
                    readAndSortItems()
         | 
| 308 | 
            +
                }
         | 
| 309 | 
            +
                func readAndSortItems() -> Void {
         | 
| 310 | 
            +
                    listData = []
         | 
| 311 | 
            +
                    itemservice.readItems() { item in
         | 
| 312 | 
            +
                        print("completion")
         | 
| 313 | 
            +
                        self.listData.append(item)
         | 
| 314 | 
            +
                    }
         | 
| 315 | 
            +
                }
         | 
| 316 | 
            +
            }
         | 
| 317 | 
            +
             | 
| 318 | 
            +
             | 
| 319 | 
            +
            //  ListView.swift
         | 
| 320 | 
            +
            import SwiftUI
         | 
| 321 | 
            +
            import Observation
         | 
| 322 | 
            +
            struct ListView: View {
         | 
| 323 | 
            +
                var gearList: GearList
         | 
| 324 | 
            +
                @State private var listVM = ListViewModel()
         | 
| 325 | 
            +
             | 
| 326 | 
            +
                init(gearList: GearList) {
         | 
| 327 | 
            +
                    self.gearList = gearList
         | 
| 328 | 
            +
                    self.listVM = ListViewModel(gearList: gearList)
         | 
| 329 | 
            +
                }
         | 
| 330 | 
            +
                
         | 
| 331 | 
            +
                var body: some View {
         | 
| 332 | 
            +
                    Button("tap", action: action)
         | 
| 333 | 
            +
                    List {
         | 
| 334 | 
            +
                        ForEach(listVM.listData.indices, id: \.self) { index in
         | 
| 335 | 
            +
                            Section(header:Text(listVM.listData[index][0].categoryname)) {
         | 
| 336 | 
            +
                                ForEach(listVM.listData[index].indices, id: \.self) { index2 in
         | 
| 337 | 
            +
                                    Text(listVM.listData[index][index2].name)
         | 
| 338 | 
            +
                                }
         | 
| 339 | 
            +
                            }
         | 
| 340 | 
            +
                        }
         | 
| 341 | 
            +
                    }
         | 
| 342 | 
            +
                }
         | 
| 343 | 
            +
                func action() {
         | 
| 344 | 
            +
                    listVM.readAndSortItems()
         | 
| 345 | 
            +
                }
         | 
| 346 | 
            +
            }
         | 
| 347 | 
            +
             | 
| 348 | 
            +
             | 
| 349 | 
            +
            ```
         | 
| 350 | 
            +
             | 
| 203 351 | 
             
            ### 試したこと
         | 
| 204 352 | 
             
            - @Observation宣言の有無や、@Stateも試してみたもののうまくいかずでした
         | 
| 205 353 |  | 
1
誤字脱字の修正をしました
    
        title	
    CHANGED
    
    | 
            File without changes
         | 
    
        body	
    CHANGED
    
    | @@ -2,11 +2,11 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            ここに実現したいことを箇条書きで書いてください。
         | 
| 4 4 | 
             
            - [ ] Swift UIで、Firestoreから取得したデータを2次元配列に格納して、List表示する
         | 
| 5 | 
            -
            - [ ] @Observableを利用して、取得データを適切に画面反映 | 
| 5 | 
            +
            - [ ] @Observableを利用して、取得データを適切に画面反映する
         | 
| 6 6 |  | 
| 7 7 | 
             
            ### 前提
         | 
| 8 8 |  | 
| 9 | 
            -
            Itemという構造体を定義し、Firestore上にそのデータを保持しています。Itemは、アイテム名の他 | 
| 9 | 
            +
            Itemという構造体を定義し、Firestore上にそのデータを保持しています。Itemは、アイテム名の他に、カテゴリー名と紐づくID(Int)を持っています。
         | 
| 10 10 | 
             
            アプリ側では、「Item配列」としてデータを取得した後、カテゴリーIDごとにアイテムを並び替え、セクション名=カテゴリー名となるようにリスト表示します。
         | 
| 11 11 | 
             
            FirestoreデータはListService内で読み込む関数を定義し(func readItems())、そのコールバックの呼び出し元をListViewModelに定義しています。
         | 
| 12 12 |  | 
