回答編集履歴

1

ソースコードを追記しました。

2024/02/14 09:51

投稿

退会済みユーザー
test CHANGED
@@ -125,3 +125,171 @@
125
125
  }
126
126
  ```
127
127
 
128
+ ### 追記です。
129
+
130
+ コードの修正ありがとうございます。
131
+ 再現確認できました。
132
+
133
+ 原因がわかりました。
134
+ `self.listVM = ListViewModel(gearList: gearList)` でlistVMを設定していますが、
135
+ この方法では@Stateとしてちゃんと設定されていないことになるみたいです。
136
+
137
+ 次のリンク先の「イニシャライザで値を設定する場合」を見てみると良いと思います。
138
+ [【SwiftUI】@Stateの使い方 | カピ通信](https://capibara1969.com/1608/#toc5)
139
+
140
+ ListViewModelのイニシャライザと、
141
+ listVMの初期値は不要になりそうですね。
142
+
143
+ 修正したコードです。
144
+ 修正ポイントに`// ***`のようなコメントを入れましたので、見てみてください。
145
+
146
+ ```swift
147
+ // ContentView.swift
148
+ import SwiftUI
149
+ struct ContentView: View {
150
+ let gearList =
151
+ GearList(
152
+ gearlistid: "gearlistid",
153
+ listname: "gearlistname",
154
+ lengthofstay: "2day",
155
+ howtostay: "Hotel",
156
+ startdate: Date(),
157
+ baseweight: 100,
158
+ consumableweight: 100,
159
+ wornweight: 100,
160
+ totalweight: 300
161
+ )
162
+ var body: some View {
163
+ ListView(gearList: gearList)
164
+ }
165
+ }
166
+
167
+ #Preview {
168
+ ContentView()
169
+ }
170
+
171
+
172
+ // Item.swift
173
+ import Foundation
174
+ struct Item: Codable, Identifiable, Hashable {
175
+ var id: String?
176
+ var brandid: String
177
+ var brandname: String
178
+ var categoryid: Int
179
+ var categoryname: String
180
+ var createdAt: Date
181
+ var itemid: String
182
+ var memo: String
183
+ var name: String
184
+ var subcategoryid: Int
185
+ var subcategoryname: String
186
+ var updatedAt: Date
187
+ }
188
+
189
+ // GearList.swift
190
+ import Foundation
191
+ struct GearList: Codable, Identifiable, Hashable {
192
+ var id: String?
193
+ var gearlistid : String
194
+ var listname : String
195
+ var lengthofstay : String
196
+ var howtostay : String
197
+ var startdate : Date
198
+ var baseweight : Int
199
+ var consumableweight : Int
200
+ var wornweight : Int
201
+ var totalweight : Int
202
+ }
203
+
204
+
205
+ // ItemService.swift
206
+ import Foundation
207
+ struct ItemService {
208
+ func readItems(gearList:GearList, completion: @escaping([Item]) -> Void) {
209
+ let items: [Item] = [
210
+ Item(brandid: "brandid",
211
+ brandname: "brandname",
212
+ categoryid: 11,
213
+ categoryname: "categoryname",
214
+ createdAt: Date(),
215
+ itemid: "itemid",
216
+ memo: "memo",
217
+ name: "name\(Int.random(in: 0..<100))",
218
+ subcategoryid: 12,
219
+ subcategoryname: "subcategoryname",
220
+ updatedAt: Date()),
221
+ Item(brandid: "brandid",
222
+ brandname: "brandname",
223
+ categoryid: 11,
224
+ categoryname: "categoryname",
225
+ createdAt: Date(),
226
+ itemid: "itemid",
227
+ memo: "memo",
228
+ name: "name\(Int.random(in: 0..<100))",
229
+ subcategoryid: 12,
230
+ subcategoryname: "subcategoryname",
231
+ updatedAt: Date()),
232
+ ]
233
+ completion(items)
234
+ }
235
+ }
236
+
237
+ // ListViewModel.swift
238
+ import Foundation
239
+ import Observation
240
+
241
+ @Observable class ListViewModel {
242
+ private let itemservice = ItemService()
243
+ private var gearList : GearList
244
+ var listData: [[Item]] = []
245
+ // *** init()コメントアウト
246
+ // init() {
247
+ // print("init")
248
+ // self.gearList = GearList(gearlistid: "", listname: "", lengthofstay: "", howtostay: "", startdate: Date(), baseweight: 0, consumableweight: 0, wornweight: 0, totalweight: 0)
249
+ // }
250
+ init(gearList:GearList) {
251
+ self.gearList = gearList
252
+ readAndSortItems(gearList:gearList)
253
+ }
254
+ func readAndSortItems(gearList:GearList) -> Void {
255
+ listData = []
256
+ itemservice.readItems(gearList:gearList) { item in
257
+ print("completion")
258
+ self.listData.append(item)
259
+ }
260
+ }
261
+ }
262
+
263
+
264
+ // ListView.swift
265
+ import SwiftUI
266
+ import Observation
267
+ struct ListView: View {
268
+ var gearList: GearList
269
+ // *** 初期値なし
270
+ @State private var listVM: ListViewModel
271
+
272
+ init(gearList: GearList) {
273
+ self.gearList = gearList
274
+ // *** @Stateをinit()で設定する場合は少し特殊な記述になります。
275
+ _listVM = State(initialValue: ListViewModel(gearList: gearList))
276
+ }
277
+
278
+ var body: some View {
279
+ Button("tap", action: action)
280
+ List {
281
+ ForEach(listVM.listData.indices, id: \.self) { index in
282
+ Section(header:Text(listVM.listData[index][0].categoryname)) {
283
+ ForEach(listVM.listData[index].indices, id: \.self) { index2 in
284
+ Text(listVM.listData[index][index2].name)
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ func action() {
291
+ listVM.readAndSortItems(gearList: gearList)
292
+ }
293
+ }
294
+ ```
295
+