Tomo.Log()


Dynamically Hide/Show View in swiftUI

[05/05, 2022]

日本語 / English

Hello Tomo, I have finally started to learn swiftUI recently.

It's been 3 years since swiftUI came out? But it's still in development and Big changes happen sometimes. I'd like to leave a note about showing and hiding a View in swiftUI.

Hiding has two meanings.

1: Hide and leave space for the View.

To hide the View, call hidden(), which makes the View invisible. Even if it becomes invisible, The space for the view will remain. It seems to be true for opacity = 0 as well.

VStack {
   Text("text1")
   Text("text2").hidden() // space will remain between text1 and text3
   Text("text3")
}

2: Hide and leave no space in the View.

According to Apple's documentation, if you don't leave space in the View, the code should not be returned a view itself.

VStack {
   Text("text1")
   if !isHidden {
      Text("text2") // no space left between text1 and text3
   }
   Text("text3")
}

Use ViewModifier to easier

I found a solution for Pattern 1 in this site

// Pattern 1
struct VisibleModifier : ViewModifier {
    let visible:Bool    
    @ViewBuilder
    func body(content: Content) -> some View {
        if visible == false {
            content.hidden()
        } else {
            content
        }
    }
}

// Pattern 2
struct HiddenModifier : ViewModifier {
    let hidden:Bool
    @ViewBuilder
    func body(content: Content) -> some View {
        if hidden {
            EmptyView()
        } else {
            content
        }
    }
}

extension View {
    func visible(_ visible:Bool) -> some View {
        modifier(VisibleModifier(visible: visible))
    }
    func hidden(_ hidden:Bool) -> some View {
        modifier(HiddenModifier(hidden: hidden))
    }
}

So I follow the code in that article and added a solution for pattern 2.
What I did for pattern 2 is return EmptyView(). And then wrap extension those two modifiers to be more useful like these below.

Text("something").visible(flag) //not visible & spaces remain
Text("something").hidden(flag) //not visible & no space left

This approach is Apple's recommended approach

I've been studying swiftUI, and I've been thinking that I can bring a lot of ideas and concepts from swiftUI to UIKit, and I think it would be good to extend UIKit.

I'm going to continue to study anyway.