UIAlertController Unable to satisfy constraints
Asked Answered
C

5

9

I am converting all my UIActionSheet and UIAlertView with UIAlertController.

My problem is when I try to present a UIAlertController of style ActionSheet. Here is my code :

UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Title"
                                                               message:@"My message"
                                                        preferredStyle:UIAlertControllerStyleActionSheet];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:cancelAction];

UIAlertAction *OKAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:OKAction];

UIAlertAction *destroyAction = [UIAlertAction actionWithTitle:@"Destroy" style:UIAlertActionStyleDestructive handler:nil];
[alert addAction:destroyAction];

UIPopoverPresentationController *popPresenter = [alert popoverPresentationController];
popPresenter.sourceView = self.view;
popPresenter.sourceRect = self.view.bounds;

[self presentViewController:alert animated:YES completion:nil];

Here is the error :

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) 
(
    "<NSLayoutConstraint:0x7c00ab40 H:[UIView:0x7c0764c0(304)]>",
    "<NSLayoutConstraint:0x7b6c7f80 _UIAlertControllerView:0x7b6c2e50'title'.width >= UIView:0x7b6c3230.width>",
    "<NSLayoutConstraint:0x7ccdfe40 _UIAlertControllerView:0x7b6c2e50'title'.width == UIView:0x7b6efbe0.width>",
    "<NSAutoresizingMaskLayoutConstraint:0x7c33b9d0 h=--& v=--& H:[UIView:0x7c1094e0(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7c00ab40 H:[UIView:0x7c0764c0(304)]>

Thank you all.

Centigram answered 30/10, 2015 at 13:37 Comment(3)
The error suggests that you try setting alert.view.translatesAutoresizingMaskIntoConstraints to NO. Have you tried this?Apogee
Yes, I tried [alert.view setTranslatesAutoresizingMaskIntoConstraints:NO]; , same issueCentigram
Did you ever figure this out? I am having the same problem.Cuisine
C
-3

I found a solution myself :

this comes from the lines :

popPresenter.sourceView = self.view;
popPresenter.sourceRect = self.view.bounds;

I have to set sourceView OR sourceRect but not both.

Centigram answered 30/10, 2015 at 14:6 Comment(4)
Well, I did this to replace all the alertView & actionSheet of my app (about 200-300) and it works perfectlyCentigram
This does not work for me as of iOS 9. It crashes and says that you need to define BOTH.Aware
Actually both should be set, but should refer to the view/button next to which the popover should appear.Cuisine
You need to set both as of iOS 10 & 11. For iPads. However this answer doesn't seem related to original question asked.Preceptory
S
4

I also encounter a similar problem in present a UIAlertController of style ActionSheet.

One more possible reason of this is setting the permittedArrowDirections of UIPopoverPresentationController wrongly. In my case, the sourceView of the popover is located at the top, but I have set the permittedArrowDirections to UIPopoverArrowDirectionDown which causes "Unable to simultaneously satisfy constraints" error. The error is gone after I set it to UIPopoverArrowDirectionUp.

Sager answered 14/12, 2015 at 6:56 Comment(1)
To complement: In general is better to allow any direction for the arrow, this way the Controller just displays the one that suits: popPresenter.permittedArrowDirections = UIPopoverArrowDirection.anyDoordie
C
0

I was having the same problem because I did not initially understand that the sourceView and sourceRect have to refer to the button/view that is pressed in connection with the action sheet. This way the popover appears next to it. If instead one uses the entire view, then the popover would appear outside the screen, which creates the constraints errors.

Cuisine answered 29/5, 2016 at 17:21 Comment(0)
L
0

I was getting this error because I was focused on a UITextField. First of all UITextField seems a little problematic, so the code below from this SO post enabled me to solve that,

extension UIView
{
    func fixInputAssistant()
    {
        for subview in self.subviews
        {
            if type(of: subview) is UITextField.Type
            {
                let item = (subview as! UITextField).inputAssistantItem
                item.leadingBarButtonGroups = []
                item.trailingBarButtonGroups = []
            }
            else if subview.subviews.count > 0
            {
                subview.fixInputAssistant()
            }
        }
    }
}

But then on validating my UITextField's my UIAlertController would kick up the constraint conflict you mention. To resolve this I needed to lose focus before showing my UIAlertController, thus

firstName.resignFirstResponder()
surname.resignFirstResponder()
emailAddress.resignFirstResponder()
... etc...

Note sure if this is relevant to your particular scenario, but be aware it could be to do with UITextField focus.

Lajuanalake answered 13/5, 2019 at 17:11 Comment(1)
Your code could be improved by writing if let textField = subview as? UITextField instead of checking the type and then force casting. Also your curly style is wrong.Stedmann
L
0

I recently faced this issue myself, and while the existing answers on this question did help, there's some extra information I found useful:

  • This error appears to happen when the given parameters would cause the alert to draw offscreen
  • You must provide either barButtonItem or both sourceView and sourceRect. If you only provide sourceView or sourceRect (not both), your app will crash (at least it did for me).
  • When providing sourceView and sourceRect, sourceRect is relative to sourceView, not the origin of the view controller presenting the alert
  • sourceView and sourceRect can be anything and don't have to be related to the button pressed as Fil's answer indicates

Chubao's answer saying to set the permitted arrow direction to Any does help fix the issue since as long as the given sourceRect is onscreen, the UIKit will pick the best arrow direction that allows the alert to be onscreen as well. However, if you are providing what you think is a valid arrow direction and run into this error, it seems more likely that you may have goofed and provided a sourceView and/or sourceRect that you didn't intend to, leading to an unexpected position of the alert, and it might be worth making sure you're passing the correct sourceView and sourceRect.

Leonardoleoncavallo answered 17/4, 2022 at 13:8 Comment(0)
C
-3

I found a solution myself :

this comes from the lines :

popPresenter.sourceView = self.view;
popPresenter.sourceRect = self.view.bounds;

I have to set sourceView OR sourceRect but not both.

Centigram answered 30/10, 2015 at 14:6 Comment(4)
Well, I did this to replace all the alertView & actionSheet of my app (about 200-300) and it works perfectlyCentigram
This does not work for me as of iOS 9. It crashes and says that you need to define BOTH.Aware
Actually both should be set, but should refer to the view/button next to which the popover should appear.Cuisine
You need to set both as of iOS 10 & 11. For iPads. However this answer doesn't seem related to original question asked.Preceptory

© 2022 - 2024 — McMap. All rights reserved.