SwiftUI Error: "Closure containing control flow statement cannot be used with function builder 'ViewBuilder'"
Asked Answered
M

2

31

I tried a SwiftUI tutorial, "Handling User Input".

https://developer.apple.com/tutorials/swiftui/handling-user-input

I tried implementing it with for instead of ForEach. But an error arose: "Closure containing control flow statement cannot be used with function builder 'ViewBuilder'".

FROM:

import SwiftUI

struct LandmarkList: View {
    @State var showFavoritesOnly = true
    
    var body: some View {
        NavigationView{
            List{
                Toggle(isOn: $showFavoritesOnly){
                    Text("Show FavatiteOnly")
                }
                
                ForEach(landmarkData) { landmark in
                    if !self.showFavoritesOnly || landmark.isFavorite {
                            NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                                LandmarkRow(landmark: landmark)
                            }
                        }
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}

TO (I wrote):

import SwiftUI

struct LandmarkList: View {
    @State var showFavoritesOnly = true
    
    var body: some View {
        NavigationView{
            List{
                Toggle(isOn: $showFavoritesOnly){
                    Text("Show FavatiteOnly")
                }
                
                for landmark in landmarkData {
                    if $showFavoritesOnly || landmark.isFavorite {
                        NavigationLink(destination: LandmarkDetail(landmark: landmark)){
                            LandmarkRow(landmark: landmark)}
                        }
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}
Modernity answered 28/6, 2020 at 2:12 Comment(2)
ForEach is a special view, but for is control flow statement which is not allowed in ViewBuilder where you try to put it in.Transgression
Why do you want to use for? The ForEach view exists precisely because a regular for loop can't be used within a view builder function. But there really isn't anything you could do with a for loop that you can't do with ForEach, so knowing what you want to achieve would help us answer your question.Iquique
S
21

The ForEach conforms to View, so at its core, it is a View just like a TextField. ForEach Relationships

You can't use a normal for-in because the ViewBuilder doesn't understand what is an imperative for-loop. The ViewBuilder can understand other control flow like if, if-else or if let using buildEither(first:), buildEither(second:), and buildif(_:) respectively.

Surah answered 17/3, 2022 at 23:27 Comment(0)
S
6

Try to comment out the if statement, and Xcode might reveal the real error to you. Here's one example: I was getting this error because of a missing associated value of an enum passed to one of my views.

Here's how it looked like before and after:

Before

Group {
    if let value = valueOrNil {
        FooView(
            bar: [
                .baz(arg1: 0, arg2: 3)
            ]
        )
    }
}

After

Group {
    if let value = valueOrNil {
        FooView(
            bar: [
                .baz(arg1: 0, arg2: 3, arg3: 6)
            ]
        )
    }
}
Sphingosine answered 25/8, 2022 at 9:16 Comment(2)
Add this to the list of non-sensical compiler issues ¯\_(ツ)_/¯ really misled me when I had just added a param in a function. Thanks!Hectorhecuba
Thanks, this was exactly my issue with the same error.Harveyharvie

© 2022 - 2025 — McMap. All rights reserved.