SwiftUIにおけるインスタンスの状態維持
現在SwiftUIにて脱出ゲームを作成しています。
基本的な機能を実装しているところなのですが、アイテムを獲得後に(isTakenがtrueになると)画面下のアイテムドックにアイテムが格納され、そしてそのアイテムをタップして選択すると(isSelectedがtrueになると)画面に再び同じアイテムが再生産されてしまいます。画面は東西南北に移動できるのですが、アイテムを選択した状態で別の画面に移動し、また同じ方角の画面に戻ってくるとこの現象が起きます。アイテムが選択されていない時は起こりません。結果的に同じアイテムを無限に獲得できでしまっている状態です。
view内の監視されている変数が変更されると自動的にviewが再描画されるとのことですが、
ItemObjectはシングルトンでインスタンスが固定されるようにしているのですが、なぜこのようなことになるのかがわかりません。
該当のソースコード
swift
1import Foundation 2 3 4struct Tool : Equatable { 5 let id : Int 6 var text: String 7 var image: String 8 var isTaken: Bool 9 var isSelected: Bool 10} 11 12 13 14class ItemObject: ObservableObject { 15 // for singleton 16 static let shared = ItemObject() 17 private init(){} 18 19 @Published var item1 = Tool(id: 1, text: "This is item 1", image: "item1.png", isTaken: false, isSelected: false) 20 @Published var item2 = Tool(id: 2, text: "This is item 2", image: "item2.png", isTaken: false, isSelected: false) 21 @Published var item3 = Tool(id: 3, text: "This is item 3", image: "item3.png", isTaken: false, isSelected: false) 22 23 24 // empty array 25 @Published var itemArray: [Tool] = [] 26 27 28} 29 30
swift
1import SwiftUI 2 3struct WindowTool: View { 4 5 @ObservedObject var itemData = ItemObject.shared 6 7 @State var putItem : Tool 8 @State var Width : CGFloat 9 @State var Height : CGFloat 10 @State var X : CGFloat 11 @State var Y : CGFloat 12 13 var body: some View { 14 if !itemData.itemArray.contains(putItem) && !putItem.isTaken { 15 { 16 Image(putItem.image).resizable() 17 }() 18 .frame(minWidth: 0 ,maxWidth: Width, minHeight: 0 ,maxHeight: Height) 19 .offset(x: X, y: Y) 20 .onTapGesture { 21 addItem(item: putItem) 22 putItem.isTaken = true 23 } 24 } 25 } 26 // to add an item 27 func addItem(item: Tool) { 28 itemData.itemArray.append(item) 29 } 30 31}
swift
1import SwiftUI 2 3struct Window: View { 4 5 @ObservedObject var windowObject = WindowObject.shared 6 @ObservedObject var itemData = ItemObject.shared 7 8 var body: some View { 9 ZStack{ 10 BackGroundPicture(imageFilename: windowObject.window.image) 11 WindowTool(putItem: itemData.item1, Width: 100, Height: 100, X: 0, Y: 0) 12 } 13 14 } 15 16} 17 18 19 20 21
ちなみにWindowObjectもItemObjectと全く同じような仕様で作成されています。
試したこと
ちなみにWindowToolのviewのputItemの変数の部分にそれぞれitemData.item1とそのままベタ書きするとこの問題は起きません。つまり、アイテムが獲得された状態が維持されています。
シングルトンで書く前は全て@EnvironmentObjectにしていました。ですが、状況は全く変わっていません。
どのような対処方法が考えられるでしょうか。再描写されるタイミングがイマイチ判断できません。
あなたの回答
tips
プレビュー