1

This issue is related to the UIToolBar layout constraints issue in iOS13. I am encountering the following layout constraints warning and I am using autolayout:

[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. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x600001018c30 h=--& v=--& _UIToolbarContentView:0x7fc8e4eacdf0.width == 0   (active)>",
    "<NSLayoutConstraint:0x600001003d40 H:|-(0)-[_UIButtonBarStackView:0x7fc8e4ead4d0]   (active, names: '|':_UIToolbarContentView:0x7fc8e4eacdf0 )>",
    "<NSLayoutConstraint:0x600001003cf0 H:[_UIButtonBarStackView:0x7fc8e4ead4d0]-(0)-|   (active, names: '|':_UIToolbarContentView:0x7fc8e4eacdf0 )>",
    "<NSLayoutConstraint:0x60000100e5d0 'TB_Leading_Leading' H:|-(16)-[_UIModernBarButton:0x7fc8e4f4e050'Add category']   (active, names: '|':_UIButtonBarButton:0x7fc8e4f4de80 )>",
    "<NSLayoutConstraint:0x60000102ec10 'TB_Trailing_Trailing' H:[_UIModernBarButton:0x7fc8e4f4e050'Add category']-(16)-|   (active, names: '|':_UIButtonBarButton:0x7fc8e4f4de80 )>",
    "<NSLayoutConstraint:0x6000010183c0 'UISV-canvas-connection' UILayoutGuide:0x600000a2a3e0'UIViewLayoutMarginsGuide'.leading == UIView:0x7fc8e4f0d920.leading   (active)>",
    "<NSLayoutConstraint:0x6000010185a0 'UISV-canvas-connection' UILayoutGuide:0x600000a2a3e0'UIViewLayoutMarginsGuide'.trailing == UIView:0x7fc8e4f4e8e0.trailing   (active)>",
    "<NSLayoutConstraint:0x6000010185f0 'UISV-spacing' H:[UIView:0x7fc8e4f0d920]-(0)-[_UIButtonBarButton:0x7fc8e4f4de80]   (active)>",
    "<NSLayoutConstraint:0x600001018640 'UISV-spacing' H:[_UIButtonBarButton:0x7fc8e4f4de80]-(0)-[UIView:0x7fc8e4f4e8e0]   (active)>",
    "<NSLayoutConstraint:0x6000010007d0 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x600000a2a3e0'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UIButtonBarStackView:0x7fc8e4ead4d0 )>",
    "<NSLayoutConstraint:0x600001001310 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600000a2a3e0'UIViewLayoutMarginsGuide']-(0)-|(LTR)   (active, names: '|':_UIButtonBarStackView:0x7fc8e4ead4d0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000102ec10 'TB_Trailing_Trailing' H:[_UIModernBarButton:0x7fc8e4f4e050'Add category']-(16)-|   (active, names: '|':_UIButtonBarButton:0x7fc8e4f4de80 )>

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.

Code:

let toolBar: UIToolbar = {
    let tb = UIToolbar()
    tb.translatesAutoresizingMaskIntoConstraints = false
    return tb
}()

fileprivate func setupView() {

    view.addSubview(toolBar)
    toolBar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    toolBar.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    toolBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

    toolBar.items = [
        UIBarButtonItem.flexibleSpace(),
        UIBarButtonItem(title: "Add category", style: .plain, target: self, action: #selector(addCategoryButtonTapped)),
        UIBarButtonItem.flexibleSpace()
    ]
}

As suggested by this post and this, specifying the toolBar's frame manually could remove the warning. However, I am not able to get the toolbar to anchor to safeAreaLayoutGuide.bottomAnchor.

Attempt:

let toolBar = UIToolbar(frame: CGRect(x: 0, y: view.bounds.height - 50 - view.safeAreaInsets.bottom, width: view.bounds.width, height: 50))
view.addSubview(toolBar)

The above code doesn't anchor the toolBar at the bottom of the safeAreaLayoutGuide and disappears on rotate.

UPDATE:

Attempting @Frankenstein's solution solves the problem when devices does not rotate. Upon rotation, the warning surfaces again. See gif:

enter image description here

Koh
  • 2,274
  • 1
  • 16
  • 49

1 Answers1

-1

UIToolbar seems to work pretty specifically. You need to first unhide the toolbar of the navigation controller and then set the toolbarItems of the ViewController. There's the code:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        setupToolbar()
    }

    func setupToolbar() {
        navigationController?.isToolbarHidden = false

        toolbarItems = [
            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
            UIBarButtonItem(title: "Some Item", style: .plain, target: nil, action: nil),
            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)]
    }
}
Frankenstein
  • 14,749
  • 4
  • 18
  • 44
  • Your code almost works. When there is no rotation of the device, it does remove the warning. However when device rotates, and then navigates to the said ViewController, the warning surfaces again. See update – Koh May 09 '20 at 04:31