Search code examples
iosipadswiftuiios13actionsheet

Unable to present ActionSheet via a NavigationBarItem in SwiftUI on an iPad


First, I have looked at a similar question, but it does not address my use case.

Present ActionSheet in SwiftUI on iPad

My issue is that I have a NavigationBarItem in my NavigationView that will toggle an ActionSheet when pressed. This behavior works properly when used on an iPhone.

However, when I use this on an iPad, both buttons on my screen will gray out and nothing happens. Clicking the buttons again will make them active (blue), but again, no sheet is presented.

Finally, if I select the button in the middle of the screen (Show Button), then an ActionSheet is properly presented on an iPad.

I have tested with Xcode 11 & iOS 13.5 and Xcode 12 & iOS 14. There is no change in behavior.

import SwiftUI

struct ContentView: View {
    @State private var isButtonSheetPresented = false
    @State private var isNavButtonSheetPresented = false

    var body: some View {
        NavigationView {
            Button(action: {
                // Works on iPad & iPhone
                self.isButtonSheetPresented.toggle()
              }) {
                Text("Show Button")
            }
            .actionSheet(isPresented: $isButtonSheetPresented,
                         content: {
                             ActionSheet(title: Text("ActionSheet"))
              })
            .navigationBarTitle(Text("Title"),
                                displayMode: .inline)
            .navigationBarItems(trailing:
                Button(action: {
                    // Works on iPhone, fails on iPad
                    self.isNavButtonSheetPresented.toggle()
                    }) {
                    Text("Show Nav")
                }
                .actionSheet(isPresented: $isNavButtonSheetPresented,
                             content: {
                                 ActionSheet(title: Text("ActionSheet"))
                    })
            )
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

Finally, this is how it appears on an iPad when clicking on "Show Nav":

enter image description here

This is a simplified setup for the screen where this issue occurs. I will need to retain the navigation settings shown, but have included them for clarity.

*** UPDATED ***

While it is not possible for the real app behind this, I did remove the .navigationViewStyle(StackNavigationViewStyle()) setting, which did make an ActionSheet appear, although in the wrong spot as seen below.

enter image description here

This also results in bizarre placement for the Button one accessed via "Show Button".

enter image description here


Solution

  • Yes, it is a bug, but probably different - that Apple does not allow to change anchor and direction of shown ActionSheet, because it is shown, but always to the right of originated control on iPad. To prove this it is enough to change location of button in Navigation

    Here is example of placing at .leading position. Tested with Xcode 12 / iOS 14

    demo

    .navigationBarItems(leading:       
        Button(action: {
            // Works on iPhone, fails on iPad
            self.isNavButtonSheetPresented.toggle()
            }) {
            Text("Show Nav")
        }
        .actionSheet(isPresented: $isNavButtonSheetPresented,
                     content: {
                         ActionSheet(title: Text("ActionSheet"))
            })
    )
    

    Note: SwiftUI 2.0 .toolbar behaves in the same way, ie. has same bug.