Search code examples
swiftswiftuidispatch-queue

Having issue with DispatchQueue not working after 3-4 executions in Swift


I have the following code below to show a Message to the user and then disappear. Everything works fine for the first 1 to 3 tries, but anything above that the Message window does not disappear as it did on the previous attempts/required.

struct ContentView: View {
    @State var showingNotice = false

    var body: some View {
        ZStack {
            Button(action: {
                self.showingNotice = true
            }, label: {
                Text("Show Notice")
            })

            if showingNotice {
                FloatingNotice(showingNotice: $showingNotice)
            }
        }
        .animation(.easeInOut(duration: 1))
    }
}

struct FloatingNotice: View {
    @Binding var showingNotice: Bool

    var body: some View {
        VStack (alignment: .center, spacing: 8) {
            Image(systemName: "checkmark")
                .foregroundColor(.white)
                .font(.system(size: 48, weight: .regular))
                .padding(EdgeInsets(top: 20, leading: 5, bottom: 5, trailing: 5))
        
            Text("Review added")
                .foregroundColor(.white)
                .font(.callout)
                .padding(EdgeInsets(top: 0, leading: 10, bottom: 5, trailing: 10))
        }
        .background(Color.snackbar.opacity(0.75))
        .cornerRadius(5)
        .transition(.scale)
        .onAppear(perform: {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
                self.showingNotice = false
            })
        })
    }
}

Can anyone see what I am missing or help figure why it "stops" working after multiple executions?


Solution

  • Sometimes onAppear will not called so your self.showingNotice = false is not getting called. So you can do one thing move your delay block inside the button click it self as below.

    struct ContentView: View {
        @State var showingNotice = false
    
        var body: some View {
            ZStack {
                Button(action: {
                    self.showingNotice = true
                    DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
                        self.showingNotice = false
                    })
                }, label: {
                    Text("Show Notice")
                })
    
                if showingNotice {
                    FloatingNotice(showingNotice: $showingNotice)
                }
            }
            .animation(.easeInOut(duration: 1))
        }
    }
    
    struct FloatingNotice: View {
        @Binding var showingNotice: Bool
    
        var body: some View {
            VStack (alignment: .center, spacing: 8) {
                Image(systemName: "checkmark")
                    .foregroundColor(.white)
                    .font(.system(size: 48, weight: .regular))
                    .padding(EdgeInsets(top: 20, leading: 5, bottom: 5, trailing: 5))
                   
            
                Text("Review added")
                    .foregroundColor(.white)
                    .font(.callout)
                    .padding(EdgeInsets(top: 0, leading: 10, bottom: 5, trailing: 10))
            }
            .background(Color(.red))
            .cornerRadius(5)
            .transition(.scale)
            
        }
    }