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

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

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

Q&A

解決済

1回答

521閲覧

【SwiftUI】ForEachを使ったViewがきちんと再描画されない

kuwatsy

総合スコア5

0グッド

1クリップ

投稿2023/02/23 14:01

実現したいこと

@StateとForEachを使ったViewの再描画をしたい

前提

SwiftUIで、ForEachを使ったViewで丸数字を指定の個数だけ並べて表示させたあと、個数を変化させて表示を再描画させたいのですが、うまくいきません。

例えば、あらかじめ@State var number = 4として表示させると、
個数の指定は4と表示され、意図通り数字が4個並びます。(①②③④)
ボタンで、1個数字を増やして5個にしようとすると、
個数の指定は5と再描画されるのに、数字の並びは4個のままです。(①②③④)
数字の並びも5個としたい(①②③④⑤)のですが、どうすればいいでしょうか?

個数指定の数字も、数字の並びも同じImageViewの中で記述しているので、ImageViewが@Stateの数字が変わったことで再描画されているはずなのですが...
どなたかご教示いただけるとありがたいです。

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

エラーメッセージはありません。

該当のソースコード

SwiftUI

1import SwiftUI 2 3struct ContentView: View { 4 @State var number = 4 5 6 var body: some View { 7 VStack { 8 ImageView(number: number).padding() 9 Button("個数 +1") { if number < 6 { number = number + 1 }} 10 Button("個数 -1") { if number > 1 { number = number - 1 }} 11 } 12 } 13} 14 15struct ImageView: View { 16 var number: Int 17 18 var body: some View { 19 VStack { 20 Text("個数の指定: \(number)").padding() 21 HStack { 22 ForEach (0..<number) { i in 23 Image(systemName: "\(i+1).circle").font(.title) 24 } 25 } 26 } 27 } 28} 29 30struct ContentView_Previews: PreviewProvider { 31 static var previews: some View { 32 ContentView() 33 } 34}

試したこと

UUID()をうまく使うと解決すると書いてあるものもありましたが、理解できませんでした。

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

Xcode 14.2

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

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

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

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

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

guest

回答1

0

ベストアンサー

このコードは、
ForEach (0..<number) { i in
の行に
Non-constant range: argument must be an integer literal
という警告が表示されていて、アプリを起動してボタンをタップするたびに、コンソールに

ForEach<Range<Int>, Int, ModifiedContent<Image, _EnvironmentKeyWritingModifier<Optional<Font>>>> count (5) != its initial count (4). `ForEach(_:content:)` should only be used for *constant* data. Instead conform data to `Identifiable` or use `ForEach(_:id:content:)` and provide an explicit `id`!

というエラーメッセージが表示されるはずです。ボタンをタップしても表示個数が変わらない原因は、そのメッセージに記載されている通りです。ForEachに指定する配列や範囲に変数を使用する場合は、Identifiableに準拠した変数を指定するか、 id 引数で、何を識別要素とするかを指定する必要があります。よくわからない時は、上記のエラーメッセージをWebで検索すれば、どのようにすればよいか解説した記事が見つかると思います。今回の場合、

ForEach (0..<number, id: \.self) { i in

のようにして、 id: \.self の引数を追加すれば表示個数が変化するようになると思います。

投稿2023/02/24 09:52

TakeOne

総合スコア6299

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

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

kuwatsy

2023/02/24 10:21

たいへんありがとうございました。 ご指摘のとおり、コードの横にいつもワーニングが表示されており、それを検索ワードにしてwebで関連する対処法を見てはいましたが、実際にどう自分のコードを変えるのか分からずにいました。 今回、具体的に変更箇所を示していただいた結果、あっという間にやりたいことが実現でき、鳥肌が立ったのと、改めて対処法の書いてあるwebを見直したところ、(今まで全く意味がわからなかった)書いてある内容が頭にどっと入ってくるようになりました。 説明もとても優しく、丁寧に解説いただき、嬉しい限りです。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問