Closure Containing a Declaration Cannot Be Used with Function Builder 'Viewbuilder'

Closure containing a declaration cannot be used with function builder 'ViewBuilder'

you shouldn't create a variable inside the SwiftUI builder block, you should create it out of the body scope,

  var isPlaying = false

var body: some View {
Text("Levels \(isPlaying)")
}

Swift UI uses a function builders block that can only contain content that is understandable by the builder.
Then what you should write inside the builder block is only View Type and [View] 
However, if you want to declare a variable you could work around it by introducing it to a new subclass

The purpose of this feature is to enable the creation of embedded DSLs in Swift -- allowing you to define content that gets translated to something else down the line

Also, you could use.

 @State var isPlaying: Bool = false

Note

review your code twice before doing the workaround, probably you have
a misunderstanding about how swift-UI works?

Closure containing control flow statement cannot be used with result builder 'ViewBuilder'

Unfortunately, your code is a little confused.

Where you see this:

struct ContentView: View {
var body: some View {
// Some Stuff here
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

That is SwiftUI code that is trying to create a user interface for your application. Unfortunately it's not like "normal" Swift code. There are some behind the scenes things going on that make it easy to create user interfaces, but hard to understand if you're new to programming.

You put your "plain old code" in the middle of the view declaration and the compiler is very confused to see it there.

Instead, let's take your code out into a function. Then you can call the function.

struct ContentView: View {
var body: some View {
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

func parseSomeHTML() {
do {
let html = """
<html>
<head>
<title>First parse</title>
</head>"
<body>
<p>Parsed HTML into a doc.</p>
</body>
</html>
"""

let doc: Document = try SwiftSoup.parse(html)
let p: Element = try doc.select("title").first()!
print(p)
} catch Exception.Error(let type, let message) {
print(message)
} catch {
print("error")
}
}

Now your code lives in a plain, ordinary Swift function. But you're going to need to call it from somewhere. Let's add a button to call your function. Change contentView to this:

struct ContentView: View {
var body: some View {
Button("Push Me", action: { parseSomeHTML() })
}
}

Now when you run your app, you should have a button, and pushing that button should call the parseSomeHTML function.

(Note how I used triple double quotes (""") to format a multi-line string with your HTML. It's not necessary, what you had should work, but it's prettier)

Why can i create local variables in a view builder in SwiftUI

When SwiftUI was first released (in 2019), the Swift language didn't allow local declarations (like let something = 3) inside what were then called “function builders”. However, function builders evolved into what are now called “result builders” and do support local declarations as of Swift 5.4.

This behavior is documented in SE-0289 Result Builders:

Declaration statements

Local declarations are left alone by the transformation. This allows developers to factor out subexpressions freely to clarify their code, without affecting the result builder transformation.

Swift UI - Closure containing control flow statement cannot be used with result builder 'CommandsBuilder'

Since .contains returns a Bool, you don't need to provide a binding to a variable (which is used in cases where you have a statement returning an Optional value).

//remove var mlOutput... line here
Group{
if let mlOutput = detector.imageClass, collectionArr.contains(mlOutput) {
HStack{
Text("").font(.caption)
Text(mlOutput).bold()
}
} else {
HStack {
Text("This is not in the array").font(.caption)
}
}
}

This is assuming that mlOuput (which maybe is a typo for mlOutput?) is a String

Closure containing control flow statement cannot be used with result builder 'CommandsBuilder'

Xcode failed to produce real error that's why he says about CommandsBuilder.

Generally when you face such problem, try to comment your code block by block to localize the problem.

In this case if you comment if .. { } else { } and left both parts of if there(just to build it), Xcode will be able to tell actual problem


In this case LinearGradient doesn't have init(colors: ..., so both lines

.mask(Circle().fill(LinearGradient(colors: [Color.black, Color.clear], startPoint: startPoint, endPoint: endPoint)))

Should be replaced with:

.mask(Circle().fill(LinearGradient(gradient: Gradient(colors: [Color.black, Color.clear]), startPoint: startPoint, endPoint: endPoint)))

If you wanna use defined below functions, like getXoffetInnerShadow, at a parameter to .offset modifier, you should replace return type to CGFloat, because that's the only type .offset accepts.

Alternative to switch statement in SwiftUI ViewBuilder block?

⚠️ 23 June 2020 Edit: From Xcode 12, both switch and if let statements will be supported in the ViewBuilder!

Thanks for the answers, guys. I’ve found a solution on Apple’s Dev Forums.
It’s answered by Kiel Gillard. The solution is to extract the switch in a function as Lu_, Linus and Mo suggested, but we have to wrap the views in AnyView for it to work – like this:

struct RootView: View {
@State var containedViewType: ContainedViewType = .home

var body: some View {
VStack {
// custom header goes here
containedView()
}
}

func containedView() -> AnyView {
switch containedViewType {
case .home: return AnyView(HomeView())
case .categories: return AnyView(CategoriesView())
...
}
}


Related Topics



Leave a reply



Submit