Brennan Cheung
Brennan Cheung

Reputation: 4541

How to write a function that takes a closure of a view and returns a view?

I'm wanting to write utilities that work with views to do things like conditionally show views and do things like intersperse where a view is repeated and some kind of separator is inserted between each iteration. I can't figure out how to define the function type signature. This is what I got so far:

    func ifNotLastCategory(_ cat: String, content: () -> AnyView) -> AnyView {
        if (cat != movie.categories.last) { return content() }
    }


    ...
    
    ifNotLastCategory(category) { Text("Hello World") }

When I try to do something like that I get a compiler error about Cannot convert value of type 'some View' to closure result type 'AnyView'. However it won't let me define content as returning some View.

How can I make this function work?

Upvotes: 1

Views: 502

Answers (2)

pawello2222
pawello2222

Reputation: 54466

Try not to use AnyView unless you really have a good reason for it. In most cases you can use other solutions which are more efficient and cleaner.

In your case I suggest using a @ViewBuilder and returning some View:

@ViewBuilder
func ifNotLastCategory<V: View>(_ cat: String, content: () -> V) -> some View {
    if cat != movie.categories.last {
        content()
    }
}

Upvotes: 3

Patrick Wynne
Patrick Wynne

Reputation: 2124

You can use a generic function and cast the result to AnyView:

func ifNotLastCategory<V: View>(_ cat: String, content: () -> V) -> AnyView {
    if cat != movie.categories.last { return AnyView(content()) }
    return AnyView(EmptyView())
}

Upvotes: 1

Related Questions