Home > other >  Strange behavior with Menu inside cells and sheetView
Strange behavior with Menu inside cells and sheetView

Time:01-24

I would like to add Menu in the cells of my list but this causes a strange behavior when I want to open the sheet view. I get the following message:

[Presentation] Attempt to present <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x1620b0800> on <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier_: 0x161811800> (from <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier_: 0x161811800>) which is already presenting <_UIContextMenuActionsOnlyViewController: 0x16051de40>.

I feel like the sheet view wants to open at the same time as the menu. How can I solve the problem?

Here is an example code that illustrates my problem:

struct Item: Identifiable{
let id: Int
let marque: String
let reference: String
}

struct ContentView: View {
    @State var items = [Item(id: 1, marque: "Schneider", reference: "123333"),     Item(id: 2, marque: "Siemens", reference: "1234444"), Item(id: 3, marque: "Beck", reference: "1233"), Item(id: 4, marque: "Aron", reference: "133449")]
    @State private var selectedItem: Item?

var body: some View {
    List {
        ForEach(items, id: \.id) { item in
            HStack {
                Text(item.marque)
                Spacer()
                Menu(content: {
                    Button("Edit") {}
                    Button("Delete") {}
                }, label: {
                    Image(systemName: "ellipsis.circle")
                })
            }
            .onTapGesture {
                self.selectedItem = item
            }
        }
    }
    .sheet(item: $selectedItem) { item in
        VStack{
            Text(item.marque)
            Text(item.reference)
        }
    }
}
}

CodePudding user response:

Yes, sheet is trying to present at the same time as Menu, as we have the TapGesture on the HStack which contains both the row and the Menu.

What is happening behind the scene? :-

  1. When we tap the ellipse (Menu), SwiftUI will try to present the Menu.
  2. But as we also have the Tap Gesture over the Row, it will update the selectedItem to item.
  3. And as the selectedItem updates, as it is binding to the sheet, SwiftUI will then also try to present sheet.
  4. And the error log prints in the console: “Attempt to present which is already presenting”. It tells you that as Self which is already presenting a Menu and therefor can not present the sheet.

So in order to fix this, let’s update our ViewTree. We will keep the Text and Menu in different stack and only add gesture to the text (Row).

List {
    ForEach(items, id: \.id) { item in
        HStack {
            HStack {
                Text(item.marque)
                Spacer()
            }
            .contentShape(Rectangle())
            .onTapGesture {
                self.selectedItem = item
            }

            Menu(content: {
                Button("Edit") {}
                Button("Delete") {}
            }, label: {
                Image(systemName: "ellipsis.circle")
            })
        }
    }
}
.sheet(item: $selectedItem) { item in
    VStack{
        Text(item.marque)
        Text(item.reference)
    }
}

This way tapping the Menu will not update the selectedItem property.

  • Related