SwiftUI `view` should be removed from the super view stack after some time
Right now, ToastMessage
is still in the hierarchy because toast()
returns ToastMessage
no matter what. Then, within toast message, there's a conditional about whether or not the actual message is displayed.
If you don't want ToastMessage
in the hierarchy at all, you'd need to move the @State
on level up so that you can use a conditional to determine whether or not it gets displayed.
// Actual View
struct FormView: View {
@State private var showToast = true
var body: some View {
Text("Hello")
.toast(show: $showToast)
.onAppear {
withAnimation { showToast = true }
}
}
}
// Toast View
struct ToastMessage<Content: View>: View {
@Binding var present: Bool
let contentView: Content
init(present: Binding<Bool>, contentView: @escaping () -> Content) {
_present = present
self.contentView = contentView()
}
var body: some View {
ZStack {
contentView
HStack {
Text("👋 You're logged in. !!")
.font(.headline)
.foregroundColor(.white)
}
.padding()
.background(Color.black.opacity(0.65))
.cornerRadius(32)
.frame(maxWidth: .infinity, alignment: .center)
.position(x: UIScreen.main.bounds.width * 0.5, y: UIScreen.main.bounds.origin.y + 80)
.transition(.move(edge: .top))
.animation(.spring(response: 0.5, dampingFraction: 1, blendDuration: 2))
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
withAnimation {
present = false
}
}
}
}
}
extension View {
@ViewBuilder func toast(show: Binding<Bool>) -> some View {
if show.wrappedValue {
ToastMessage(present: show,contentView: {self})
} else {
self
}
}
}
That being said, if you don't want to move the state up, there's not necessarily any harm in keeping ToastMessage
in the hierarchy.