Reputation: 131
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
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
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