How can I detect Empty Content as input content in SwiftUI?

Viewed 603

I have a CustomView which has a simple logic! If this CustomView get a non EmptyView should return an HStack, and If this CustomView get an EmptyView should return a Circle, how could I find out the right option depending on input content?


for example it should work like this: But it does not! I must hard code true or false for the result you see in down

CustomView() { Text("Hello") }.background(Color.red).padding()

enter image description here


CustomView().background(Color.red)

enter image description here


Goal: This question try find an answer to set right value for useHStack value depending on input content!

PS: Logically there is a way to use useHStack as parameter of CustomView, in this case there was no need to ask this question! So we are trying solve the issue without using useHStack as input parameter of CustomView or any other also! I like detect at initialization on CustomView not in body or through GeometryReader and so on . . .

My issue is there, how can I know when useHStack must be true or false depending on incoming content! incoming content means from example: Text("Hello")


import SwiftUI

struct ContentView: View {
    var body: some View {

        CustomView() { Text("Hello") }
        
        CustomView()
        
    }
}



struct CustomView<Content: View>: View {
    
    let content: () -> Content
    
    let useHStack: Bool
    
    init(@ViewBuilder content: @escaping () -> Content) {
        
        self.content = content
        self.useHStack = true // or: false depending on content(), if we got EmptyView() then false otherwise true! the idea is make this part Automatic!
        
    }
    
    init() where Content == EmptyView {
        
        self.init(content: { EmptyView() })

    }
    
    var body: some View {

        if useHStack {
            
            HStack {
                
                content()
                
                Spacer()
                
                Circle().frame(width: 50, height: 50, alignment: .center)
                
            }
            
        }
        else {
            
            Circle().frame(width: 50, height: 50, alignment: .center)
            
        }
 
    }
    
}
1 Answers

You can set useHStack to false inside the init() where Content == EmptyView. You either would need to make it var useHStack: Bool, or create a private init:

private init(content: @escaping () -> Content, useHStack: Bool) {
    self.content = content
    self.useHStack = useHStack
}

init(@ViewBuilder content: @escaping () -> Content) {
    self.init(content: content, useHStack: true)
}

init() where Content == EmptyView {
    self.init(content: { EmptyView() }, useHStack: false)
}
Related