SwiftUI & Layout API. Extra trailing closure passed in call

Hello

I'm trying to compose a layout using the Layout API.

I have already written the code for both the Layout Stack I want to use and the view I am using it in, however I am getting an "Extra trailing closure passed in call" error in the view I am using the Stack in.

Here is the code:

import SwiftUI
struct StairsView: View {
    var body: some View {
        Group{
            MyStairsStack{
                Text("Hello, World!")
                
                Text("Hello, World!")
                
                Text("Hello, World!")
            }
        }
    }
}

struct MyStairsStack: Layout{
    func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout Void) -> CGSize {
        return .init(width: proposal.width ?? 0, height: proposal.height ?? 0)
    }
    
    func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout Void) {
        guard !subviews.isEmpty else { return }
        
        let viewSize = maxSize(subViews: subviews)
        
        var origin = bounds.origin
        let maxWidth = bounds.width
        
        subviews.forEach { view in
            if (origin.x + (viewSize.width + 10) >= maxWidth){
                origin.x = bounds.origin.x
            }
            
            view.place(at: origin, proposal: proposal)
            origin.x += (viewSize.width + 10)
            origin.y += (viewSize.height + 10)
        }
    }
    
    private func maxSize(subViews: Subviews) -> CGSize{
        subViews.map { $0.sizeThatFits(.unspecified) }.reduce(.zero) { currentMax, subviewSize in
            CGSize(
                width: max(currentMax.width, subviewSize.width),
                height: max(currentMax.height, subviewSize.height))
        }
    }
}

The error is at line 5

Thank You for your time

Accepted Reply

The method behind the trailing closure accepts a closure as a parameter that can only return a single view.

func callAsFunction<V>(_ content: () -> V) -> some View where V : View

Since its not marked with @ViewBuilder, like most of the other SwiftUI view closures, you can only return one view.

So your view will have to be declared like this if you want multiple views:

MyStairsStack() {
    Group {
        Text("Hello, World!")
        Text("Hello, World!")
        Text("Hello, World!")
    }
}
  • Thank You

Add a Comment

Replies

You need to add parentheses before you add the trailing closure, like this:

MyStairsStack() {
  ...
}

Read through the documentation and it tells you how to initialise custom Layout instances, easier ways to do it as well as why.

  • Hello I've already tried this but it didn't work

Add a Comment

The method behind the trailing closure accepts a closure as a parameter that can only return a single view.

func callAsFunction<V>(_ content: () -> V) -> some View where V : View

Since its not marked with @ViewBuilder, like most of the other SwiftUI view closures, you can only return one view.

So your view will have to be declared like this if you want multiple views:

MyStairsStack() {
    Group {
        Text("Hello, World!")
        Text("Hello, World!")
        Text("Hello, World!")
    }
}
  • Thank You

Add a Comment