Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to force a Custom Layout to accept View content in @ViewBuilder

I’ve created a custom layout and since they are available on iOS >=16 I would like to use a @ViewBuilder to hide it with its fallback code:

So instead of having this in my View:

if #available(iOS 16, *) {
    CustomLayout() {
        Text("Hello, World!")
    }
} else {
    VStack(alignment: .leading) {
        Text("Hello, World!")
    }
}

I would like to hide it behind:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

struct ProportionalView<Content: View>: View {
    @ViewBuilder var content: () -> Content

    var body: some View {
        if #available(iOS 16.0, *) {
            CustomLayout() { content } // 👈 Here is what's wrong
        } else {
            VStack(alignment: .leading, content: content)
        }
    }
}


//Then use it in the View as:
ProportionalView {
    Text("Hello, World!")
}

Pretty standard SwiftUI practic. But it looks like the Custom Layout doesn’t work this way. While it accepts type View in SwiftUI View code, it doesn’t accept it here and gives an error: "Type '() -> Content' cannot conform to 'View'". And if I wrap it in Group { } an error No exact matches in reference to static method 'buildExpression'

Is there a way to force Custom Layout accept a View in @ViewBuilder?

>Solution :

You declared content like this:

@ViewBuilder var content: () -> Content

which means it is a function. To get a View, you have to actually call the function:

CustomLayout() { content() }
                     // ^^ add parens to call the function

But for the code you posted, it’s probably better to change content to not be a function, as it will be slightly more efficient due to not storing an escaping closure on the heap:

struct ProportionalView<Content: View>: View {
    @ViewBuilder var content: Content
                          //  ^^^^^^^ change type

    var body: some View {
        if #available(iOS 16.0, *) {
            CustomLayout() { content }
        } else {
            VStack(
                alignment: .leading,
                content: { content }
                      // ^^^^^^^^^^^ wrap this use in a function
            )                                     
        }
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading