1

Current situation:

I'm trying to create a reusable view in SwiftUI that returns another view passed into it. At the moment I'm using a closure that returns AnyView, as the parameter. When I initialize the reusable view I pass on a custom view wrapped inside AnyView().

Goal:

Ideally I'd like a way to omit the AnyView() wrapper and just pass on my CustomViewA or CustomViewB as is.

My attempts and issues:

I tried changing the closure parameter to return some View but I'm getting the following error:

'some' types are only implemented for the declared type of properties and subscripts and the return type of functions

I've seen a few attempts on S.O. to work around that by somehow using a generic parameter but I'm not sure how to implement this in my case or if it's even possible. Also important to note, the closure needs to take a String as its own input parameter.

Example code:

import SwiftUI

struct ReusableView: View {
    let outputView: (String) -> AnyView
    
    var body: some View {
        outputView("Hello World")
    }
}

struct CustomViewA: View {
    let label: String
    
    init(_ label: String) {
        self.label = label
    }
    var body: some View {
        return Text(label)
    }
}

struct CustomViewB: View {
    let label: String
    
    init(_ label: String) {
        self.label = label
    }
    var body: some View {
        return HStack{
            Text(label)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ReusableView() {
            AnyView(CustomViewA($0))
        }
    }
}
Marco Boerner
  • 1,243
  • 1
  • 11
  • 34

1 Answers1

1

You just need to make ReusableView generic and declare the return type of your closure as the generic type.

struct ReusableView<Output: View>: View {
    let outputView: (String) -> Output
    
    var body: some View {
        outputView("Hello World")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ReusableView() {
            CustomViewA($0)
        }
    }
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116