4265756b69
4265756b69

Reputation: 57

Why my toolbar button dissapears in SwiftUI?

I have a little issue and I don't know how to fix it. I have aa view with a button, and when the button is clicked, the status changes and my toolbar button need to change to, but on the first time, my toolbar button is dissapearing. If a terminate the app and enter again, my toolbar button appears, and if I am trying to do the same thing again, press the button, my toolbar is not dissapearing anymore, only the first time . It happens only on the first time / device.

if syncViewModel._order.id == coreDataViewModel.savedCartOrders.first?.id ?? 0{
                if syncViewModel._order.status == canceledStatus {
                    NavigationLink(destination: CartView()
                                    .onAppear {
                        print("Completed or Canceled")
                    }
                                    .toolbar {
                                        ToolbarItem(placement: .navigationBarLeading) {
                                        }
                                    }
                                   , label: {
                         Image("cartIcon")
                            .foregroundColor(Color.onboardingColor)
                    }
                    )
                }
                else  {
                    NavigationLink(isActive: $pushActive) {
                        WaitingOrderView()
                    } label: {
                       Text("Order Active")
                    }

                }

Upvotes: 0

Views: 1023

Answers (1)

Roland Lariotte
Roland Lariotte

Reputation: 3512

The toolbar must be placed inside the NavigationView as shown in the code below.

The .onAppear must be placed inside the view where you want things to happen. It is easier to have it at the bottom of it, like shown in the code below.

The thing is that you can always add more boolean value to show/hide elements in a SwiftUI view. And it can also work on the toolbar element, even though it is not placed inside the "action".

This is how I would put the logic in your view.

struct ContentView: View {

  let myOrder = Order()
  let savedOrder = [Order(id: 2, status: .pending)]

  @State var isActive = false
  @State var isCartEmpty = false

  var body: some View {
    NavigationView {
      VStack(spacing: 60) {
        if myOrder.id == savedOrder.first?.id ?? .zero {
          if myOrder.status == .pending {
            NavigationLink(destination: CartView(),
                           label: {
              HStack { // NavigationLink button
              Image(systemName: "bolt.car.circle.fill")
                .resizable()
                .frame(width: 60, height: 60)

                Text("Press me")
                  .font(.headline)
              }
              .foregroundColor(.green)
            })
          }
          else  {
            NavigationLink(isActive: $isActive) {
              WaitingOrderView()
            } label: {
              Text("Order Active")
                .foregroundColor(.primary)
            }
          }
        }

        Button(action: { isCartEmpty.toggle() }) { // Change toolbar item
          Text("Add Item")
            .font(.headline)
        }
        .buttonStyle(.borderedProminent)
        .foregroundColor(.yellow)
      }
      .toolbar { // Where the toolbar must be placed
        ToolbarItem(placement: .navigationBarLeading) {
          if myOrder.status == .pending {
            Button(action: {}) {
              Image(systemName: isCartEmpty // Change image with bool
                      ? "cart.badge.plus"
                      : "cart.fill.badge.plus")
                .foregroundColor(isCartEmpty ? .yellow : .red)
            }
          }
        }
      }
    } // End of NavigationView
  }
}

This is data and Views I added to make the code compile.

struct Order {
  var id = 2
  var status: Status = .pending
}

enum Status {
  case cancel
  case pending
}

struct CartView: View {
  var body: some View {
    VStack {
      Text("CartView")
    }
    .onAppear {  // Add onAppear at the bottom of the needed view
      print("Completed or Canceled")
    }
  }
}

struct WaitingOrderView: View {
  var body: some View {
    Text("WaitingOrderView")
  }
}

Upvotes: 1

Related Questions