Skip to main content

Blink/Views/Helpers/DeferredRendering.swift

1import SwiftUI
3/// Defers the rendering of a view for the given period.
4///
5/// For example:
6///
7/// ```swift
8/// Text("Hello, world!")
9/// .deferredRendering(for: .seconds(5))
10/// ```
11///
12/// will not display the text "Hello, world!" until five seconds after the
13/// view is initially rendered. If the view is destroyed within the delay,
14/// it never renders.
15///
16/// This is based on code xwritten by Yonat and Charlton Provatas on
17/// Stack Overflow, see https://stackoverflow.com/a/74765430/1558022
18///
19private struct DeferredViewModifier: ViewModifier {
20 let delay: DispatchTimeInterval
22 func body(content: Content) -> some View {
23 _content(content)
24 .onAppear {
25 DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
26 self.shouldRender = true
27 }
28 }
29 }
31 @ViewBuilder
32 private func _content(_ content: Content) -> some View {
33 if shouldRender {
34 content
35 } else {
36 content.hidden()
37 }
38 }
40 @State private var shouldRender = false
43extension View {
44 func deferredRendering(for delay: DispatchTimeInterval) -> some View {
45 modifier(DeferredViewModifier(delay: delay))
46 }
49struct DeferredRendering_Previews: PreviewProvider {
50 static var previews: some View {
51 VStack {
52 Text("This text renders immediately")
53 Text("This text appears after a delay")
54 .deferredRendering(for: .seconds(1))
55 }
56 }