Lina_F
Lina_F

Reputation: 131

SwiftUI show custom View with delay

I have something like this in my ZStack :

if hidePopup {
      CustomButton()
      .hidden()
 } else if stateManager.isBtnClosePressed {
      CustomButton()
      .hidden()
 } else {
      CustomButton()
 }

And I need in the last else to show CustomButton() with some delay. I’ve tried to wrap it in DispatchQueue.main.async but it doesn’t suit there. I mean:

DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
      CustomButton()
 } 

TIA for your opinions and help

Upvotes: 8

Views: 9489

Answers (2)

Charlton Provatas
Charlton Provatas

Reputation: 2274

Adding to @Yonat's answer– You can use this as a view modifier

/// A ViewModifier that defers its rendering until after the provided threshold surpasses
private struct DeferredViewModifier: ViewModifier {

    // MARK: API

    let threshold: Double

    // MARK: - ViewModifier

    func body(content: Content) -> some View {
        _content(content)
            .onAppear {
               DispatchQueue.main.asyncAfter(deadline: .now() + threshold) {
                   self.shouldRender = true
               }
            }
    }

    // MARK: - Private

    @ViewBuilder
    private func _content(_ content: Content) -> some View {
        if shouldRender {
            content
        } else {
            content
                .hidden()
        }
    }

    @State
    private var shouldRender = false
}

extension View {
    func deferredRendering(for seconds: Double) -> some View {
        modifier(DeferredViewModifier(threshold: seconds))
    }
}

Usage:

struct MyView: View {
    var body: some View {
        Text("test")
           .deferredRendering(for: 0.5)
    } 
}

Upvotes: 6

Yonat
Yonat

Reputation: 4608

You need to change a @State var after the delay. For example:

struct ContentView: View {
    @State var isButtonHidden = true
    let button = Button("Custom", action: {})

    var body: some View {
        Group {
            if isButtonHidden {
                button.hidden()
            } else {
                button
            }
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
                self.isButtonHidden = false
            }
        }
    }
}

Upvotes: 22

Related Questions