80928


`SwiftUI`でのView配列のForEachがindexで回そうとした時に、`forEach(配列)`では動作してくれるのですが、`forEach(0...配列.count)`だと動いてくれません。  
これは仕様でしょうか？  
何か対策はあるでしょうか？

[code]

    struct MainView: View {
        @State var subViewList: [SubView] = []
        
        var body: some View {
            VStack {
                Button("ADD", action: {
                    self.subViewList.append(SubView())
                })
                
                ForEach(self.subViewList) { subView in
                    return subView
                }
                
                // 動作しない
                ForEach(0..<self.subViewList.count) { index in
                    return self.subViewList[index]
                }
            }
    
        }
    }
    
    struct SubView: View, Identifiable {
        let id = UUID()
        
        var body: some View {
            Text("SubView")
        }
    }
    
[/code]


CC BY-SA 4.0
2021-08-19T14:49:21.227
80923
2021-08-19T22:14:15.487
40856
question
swift swiftui
SwiftUIでのView配列のForEachがindexで回すと動作しない問題


> これは仕様でしょうか？

仕様です。

[`ForEach.init(_ data: Range<Int>, content: @escaping (Int) ->
Content)`](https://developer.apple.com/documentation/swiftui/foreach/init\(_:content:\)-6db7u)のDiscussionには次のように記載されています。

> ## Discussion
>
> The instance only reads the initial value of the provided `data` and doesn’t
> need to identify views across updates. To compute views on demand over a
> dynamic range, use `ForEach`/`init(_:id:content:)`.

わかりにくい表現ですが、実際の動作に沿って超意訳してみると「最初に繰り返しviewを作った時点から中身が変化したってしらねぇよ」と言う意味だと思ってください。

動的に変化する内容を扱うなら、先のDiscussionに書いてあるよう`init(_:id:content:)`を使用してください。

Viewを配列に持つのは色々予期せぬことが起こりうるのでお勧めできませんから、その辺も修正するとこんな感じです。

[code]

    struct MainView: View {
        @State var subViewItems: [SubViewItem] = []
        
        var body: some View {
            VStack {
                Button("ADD", action: {
                    self.subViewItems.append(SubViewItem())
                })
                
                ForEach(subViewItems) { item in
                    SubView(item: item)
                }
                
                ForEach(0..<subViewItems.count, id: \.self) { index in
                    SubView(item: subViewItems[index])
                }
            }
    
        }
    }
    
    struct SubViewItem: Identifiable {
        let id = UUID()
    
    }
    
    struct SubView: View {
        let item: SubViewItem
        
        var body: some View {
            Text("SubView")
        }
    }
    
[/code]


CC BY-SA 4.0
2021-08-19T22:14:15.487
80928
2021-08-19T22:14:15.487
13972
80923
answer