質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

0回答

2611閲覧

SwiftUIでStateデータ更新時にListのリアルタイム再描画が行われない

eleele28

総合スコア18

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2021/11/03 12:44

前提・実現したいこと

SwiftUIにて、とある処理の結果一覧をListにて表示する画面を作っています。(画像①を参考)
別途用意した絞り込みウインドウにて検索条件を指定すると、結果一覧の表示内容が絞り込み条件によってリアルタイムに変わるようにしたいです。
おまけとして、Listのセルをタップするとその結果について詳細が見られる詳細ウィンドウを別途開く機能もついています。

仕組みとしては、フィルタリング済みの結果一覧配列をStateとして画面内に宣言しておき、Listではその配列を元に描画を行うことで表示の更新を行うオーソドックスな思想です。

↓画像①:結果一覧画面
イメージ説明

発生している問題・エラーメッセージ

絞り込み条件を指定して結果配列をフィルタリングするまではうまく行ったのですが、
フィルタリング済みの結果配列を使ってListを再描画する部位に以下の問題点が発生しました。

1.フィルタリングしてもすぐにはListの表示内容が更新されない。
画像②は処理結果が「NG」である結果レコードのみを絞り込んだ状態です。
絞り込みを行ったため左上に表示されている件数表示は変化しており、各セルをタップしたときに表示される詳細ウィンドウの内容も正しいので内部的には絞り込み済み結果配列データは正しく更新されているようですが、見た目だけが更新されない状態となっています。
(なお、リストの表示される長さだけは更新されます。画像②の場合ですと、見た目のリストは9件目でぶった切られている状態です)

↓画像②:処理結果「NG」のみで絞り込んだ状態
イメージ説明

2.ただし、List内のセルに再描画がかかると見た目も更新される
画像③は処理結果「NG」も「OK」も除外したため、フィルタリング結果が0件となっている状態です。
0件であるためリストには何も表示されておりません。
ここから改めて、処理結果が「NG」である結果レコードのみを絞り込むと、画像④のように今度は見た目も正しく更新されます。
(なお、再描画がかかれば何でも良いらしく、リストをスクロールして見た目が更新されてないセルを見えない部位に追いやってから、改めてスクロールしてリストの位置をもとに戻すと、先程まで見た目が更新されていなかったセルも更新されます。)

↓画像③:一旦0件となるようにフィルタリングしてリストを消す
イメージ説明

↓画像④:改めてNGのみでフィルタリング
イメージ説明

リスト内セルの再描画をきちんと行うにはどうすればよいのでしょうか?

該当のソースコード

Swift

1import SwiftUI 2 3struct ResultHeadListView: View { 4 //全結果リストが格納されている配列 5 @Binding var resultList: [ResultRow] 6 //絞り込み済みの結果リストが格納されている配列 7 @State var filteredResults: [ResultRow] = [ResultRow()] 8 //詳細ウィンドウ表示フラグ 9 @State var isModalResultShowing: Bool = false 10 //絞り込みウィンドウ表示フラグ 11 @State var isModalSearchViewShowing: Bool = false 12 //リストのタップ位置を記憶しておくメンバ 13 @State var tappedListIdx: Int = 0 14 //検索条件データをObservedとして子ウィンドウから受け取る 15 @ObservedObject var searchCondtion: SearchResultConditions = SearchResultConditions() 16 17 var body: some View { 18 19 20 VStack { 21 22 HStack { 23 //現在表示中の件数を表示 24 Text("(self.filteredResults.count)件表示中 (全(self.resultList.count)件)") 25 .frame(maxWidth: .infinity, alignment: .leading) 26 .padding(EdgeInsets(top: 20, leading: 20, bottom: 10, trailing: 20)) 27 28 //絞り込みボタン配置 29 Button(action: { 30 //絞り込みウインドウ表示フラグをON 31 isModalSearchViewShowing = true 32 }, label: { 33 34 VStack { 35 Image(systemName: "magnifyingglass") 36 .resizable() 37 .frame(width: 30,height: 30, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) 38 } 39 40 41 }) 42 .frame(maxWidth: .infinity, alignment: /*@START_MENU_TOKEN@*/.trailing/*@END_MENU_TOKEN@*/) 43 .padding(EdgeInsets(top: 20, leading: 20, bottom: 10, trailing: 20)) 44 .sheet(isPresented: $isModalSearchViewShowing, onDismiss: { 45 //シートを閉じた際に条件抽出を行う 46 self.filteringResults() 47 48 }, content: { 49 //絞り込みウインドウに検索条件をEnvironment参照として与えてモーダル表示 50 ResultSearchView().environmentObject(self.searchCondtion) 51 }) 52 } 53 54 //絞り込み済み結果配列を使ってリストを表示 55 List { 56 ForEach (0..<self.filteredResults.count, id: .self) { idx in 57 ResultRowView(result: self.filteredResults[idx]) 58 .id(idx) 59 .onTapGesture { 60 //リストタップ時には詳細ウィンドウをモーダル表示するようにする 61 isModalResultShowing = true 62 //タップされた位置を記憶する 63 self.tappedListIdx = idx 64 } 65 .sheet(isPresented: $isModalResultShowing, content: { 66 //タップ時の詳細ウィンドウ表示 67 ResultModalWindowView( 68 resultList: self.$filteredResults[self.tappedListIdx]) 69 }) 70 71 } 72 } 73 } 74 .onAppear(perform: { 75 //初回表示時には全結果をそのまま表示内容とするためにコピーする 76 self.filteredResults = self.resultList 77 }) 78 79 } 80 81 private func filteringResults() { 82 //検索条件で検索する 83 self.filteredResults = self.resultList.filter{ record in 84 85 ~~~検索条件~~~ 86 87 } 88 } 89} 90

補足情報(FW/ツールのバージョンなど)

Xcode:Ver.12.3
シミュレータiOS:14.3
Swift:Ver.5.3.2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問