ActionSheet & StackNavigationViewStyle constraint iPad bug

Hi everybody !


When I have a NavigationView and I want to make appear the actionSheet popover on the navigationBarItem button it works.

But when I add a StackNavigationViewStyle it doesn't work anymore. This NavigationViewStyle break the actionSheet and it will not appear when I tap "+" button. I think there is a constraint problem in SwiftUI with ActionSheet and StackNavigationViewStyle in the NavigationView.


navigationViewStyle(StackNavigationViewStyle())


This is the complete code


struct ContentView: View {


    @State private var showNewControlActionSheet = false


    var body: some View {
        NavigationView {
            Text("test")
            .navigationBarTitle("Test")
            .navigationBarItems(trailing: HStack() {
                    Button(action: {
                        self.showNewControlActionSheet = true
                    }) {
                        HStack {
                            Image(systemName: "plus")
                            .padding(10)
                            .clipShape(Circle())
                        }


                    }
                    .actionSheet(isPresented: $showNewControlActionSheet) {
                        ActionSheet(title: Text("Change background"), message: Text("Select a new color"), buttons: [
                            .default(Text("Red")) {  },
                            .default(Text("Green")) {  },
                            .default(Text("Blue")) {  },
                            .cancel()
                        ])
                    }
            })
        }.navigationViewStyle(StackNavigationViewStyle())
    }
}


It works very well on iPhone but NOT on iPAD

I tried both with and without .navigationViewStyle(StackNavigationViewStyle())


No difference.

I get the selection sheet, nothing when I select a color.


What do you expect ?

What do you get with .navigationViewStyle(StackNavigationViewStyle())

What do you get without .navigationViewStyle(StackNavigationViewStyle())

I have the same problem on iPad. Without navigation view style the action sheet ist displayed, but too much on the right side. With StackNavigationViewStyle() it is not displayed at all. <edit> It is only a problem when it is a trailing button. </edit> In both cases it prints an error like this:


---


2020-04-27 16:55:02.415121+0200 ***[1077:158890] [LayoutConstraints] Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't want.

Try this:

(1) look at each constraint and try to figure out which you don't expect;

(2) find the code that added the unwanted constraint or constraints and fix it.

(

"<NSLayoutConstraint:*** UIView:***.width == - 16 (active)>"

)



Will attempt to recover by breaking constraint

<NSLayoutConstraint:*** UIView:***.width == - 16 (active)>



Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.

The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.


---


(Added some *** in the log.)

I think that's my usual problem, pressing the "+" key does not show the popover actionsheet in the right position.


https://i.postimg.cc/GtwQjgLQ/Simulator-Screen-Shot-i-Pad-7th-generation-2020-04-29-at-12-00-59.png

Sorry,


I forgot to clarify something very important. It works very well on the iPhone but not on the iPad.


What do you expect ?

• I want to display a popover on iPad

What do you get with .navigationViewStyle(StackNavigationViewStyle())

• Nothing appear

What do you get without .navigationViewStyle(StackNavigationViewStyle())

• It works pretty good, the popover appear but not at the good position and I don't want to use this SplitView.


Sorry for my forget

Same here.
Until this issue is solved, you can use this library as a workaround.
https://github.com/AndreaMiotto/ActionOver

Thought this might be fixed by 14 but it's not, this is my source code:

Code Block
import SwiftUI
struct ContentView: View {
  var body: some View {
    NavigationView {
      VStack {
        Text("Hello Things")
          .navigationModifier()
      }
    }
  }
}
struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}
extension View {
  func navigationModifier() -> some View {
    self.modifier(NavigationViewModifier())
  }
}
struct NavigationViewModifier: ViewModifier {
  @State private var showingMenu: Bool = false
   
  func body(content: Content) -> some View {
    content
      .navigationBarItems(trailing:
                  Button(action: showMenu) {
                    Text("Hello Menu")
                  }
                  .actionSheet(isPresented: $showingMenu, content: {
                    ActionSheet(title: Text("Menu"), message: nil, buttons: [.default(Text("Click Me"), action: menuAction), .cancel()])
                  })
      )
  }
   
  func showMenu() {
    self.showingMenu = true
  }
   
  func menuAction() {}
}


Once you open the left panel and click the navigation button the actionsheet shows up on the right of the view.

I had a similar issue where sometimes the action sheet would show from a button in a scroll view but after the button is scrolled or reloaded, the action sheet would stop showing. After searching the web and coming here, I realized that there is something really buggy with actionSheet and its attachment to the binding. So just for debugging I added a .onChange(of:) after the actionSheet call to log the state of the bool binding. After adding that then magically the action sheet was showing consistently.

So maybe you can try your code again with something like this:

struct ContentView: View {


    @State private var showNewControlActionSheet = false


    var body: some View {
        NavigationView {
            Text("test")
            .navigationBarTitle("Test")
            .navigationBarItems(trailing: HStack() {
                    Button(action: {
                        self.showNewControlActionSheet = true
                    }) {
                        HStack {
                            Image(systemName: "plus")
                            .padding(10)
                            .clipShape(Circle())
                        }


                    }
                    .actionSheet(isPresented: $showNewControlActionSheet) {
                        ActionSheet(title: Text("Change background"), message: Text("Select a new color"), buttons: [
                            .default(Text("Red")) {  },
                            .default(Text("Green")) {  },
                            .default(Text("Blue")) {  },
                            .cancel()
                        ])
                    }
                    //  👇 HERE IS THE TRICK I USED TO GET IT TO WORK
                   .onChange(of: showNewControlActionSheet) { newValue  in
                          print("Action sheet show flag is: \(newValue)")
                   }
            })
        }.navigationViewStyle(StackNavigationViewStyle())
    }
}

I really hope this helps anyone. Hopefully Apple can fix this weird bug

ActionSheet &amp; StackNavigationViewStyle constraint iPad bug
 
 
Q