Ich versuche, einen Standard-AlertViewController mit dem Stil .actionSheet zu verwenden . Aus irgendeinem Grund verursacht die Warnung einen Einschränkungsfehler . Solange der alertController nicht über eine Schaltfläche ausgelöst (angezeigt) wird, gibt es in der gesamten Ansicht keine Einschränkungsfehler. Könnte es sein, dass dies ein Fehler von Xcode ist?
Der genaue Fehler, den ich bekomme, sieht folgendermaßen aus:
2019-04-12 15:33:29.584076+0200 Appname[4688:39368] [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:0x6000025a1e50 UIView:0x7f88fcf6ce60.width == - 16 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000025a1e50 UIView:0x7f88fcf6ce60.width == - 16 (active)>
Dies ist der Code, den ich benutze:
@objc func changeProfileImageTapped(){
print("ChangeProfileImageButton tapped!")
let alert = UIAlertController(title: "Change your profile image", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Online Stock Library", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.view.tintColor = ColorCodes.logoPrimaryColor
self.present(alert, animated: true)
}
Wie Sie sehen können, ist es sehr einfach . Deshalb bin ich sehr verwirrt über das seltsame Verhalten, das ich bekomme, da diese Standardimplementierung keine Fehler verursachen sollte, oder?
Obwohl die Warnung durch Aufheben der Einschränkungen auf allen Bildschirmgrößen korrekt angezeigt wird, wäre ich für jede Hilfe, die ich bekomme, sehr dankbar.
Antworten:
Dieser Fehler ist nicht kritisch, scheint ein nicht behobener Fehler von Apple zu sein. Diese Einschränkung wird unmittelbar nach der Präsentation im Animationsstil angezeigt. Ich habe versucht, es zu erfassen und zu ändern (Werte, Beziehungen, Priorität ändern), bevor ich es präsentiere - kein Erfolg aufgrund dieser dynamisch hinzugefügten Einschränkungen.
Wenn Sie die Animation ausschalten
self.present(alert, animated: false)
und verwendenalert.view.addSubview(UIView())
, verschwindet der Fehler. Ich kann es nicht erklären, aber es funktioniert!let alert = UIAlertController(title: "Change your profile image", message: nil, preferredStyle: .actionSheet) alert.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: nil)) alert.addAction(UIAlertAction(title: "Online Stock Library", style: .default, handler: nil)) let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: nil) alert.addAction(cancel) alert.view.addSubview(UIView()) // I can't explain it, but it works! self.present(alert, animated: false)
quelle
alert.view.addSubview(UIView())
hat bei mir funktioniert. Aber ohne die Animation fühlt es sich so komisch an ... Trotzdem danke für diese Lösung.animation
true festgelegt ist. Ich denke, es ist ein interner Fehler und er kann ignoriert werden, da das actoinSheet richtig angezeigt wird. Ich bin froh, dass ich es auf die Grundursache eingrenzen konnte. Zuerst habe ich gelernt, dass es mein Code ist.Im Folgenden wird die Warnung entfernt, ohne dass die Animation deaktiviert werden muss. Und wenn Apple schließlich die Grundursache der Warnung behebt, sollte nichts anderes kaputt gehen.
extension UIAlertController { func pruneNegativeWidthConstraints() { for subView in self.view.subviews { for constraint in subView.constraints where constraint.debugDescription.contains("width == - 16") { subView.removeConstraint(constraint) } } } }
Dies kann dann folgendermaßen verwendet werden:
// After all addActions(...), just before calling present(...) alertController.pruneNegativeWidthConstraints()
quelle
Es ist ein neuer Fehler in iOS-Versionen:
Das einzige, was wir tun können, ist, einen Fehlerbericht bei Apple einzureichen (das habe ich gerade getan, und Sie sollten es auch tun).
Ich werde versuchen, die Antwort für eine neue Version von iOS zu aktualisieren, wenn sie herauskommt.
quelle
Hinzufügen zu dieser Antwort ... Dies scheint das Problem für mich zu beseitigen und erfordert keine Änderungen am vorhandenen Code.
extension UIAlertController { override open func viewDidLoad() { super.viewDidLoad() pruneNegativeWidthConstraints() } func pruneNegativeWidthConstraints() { for subView in self.view.subviews { for constraint in subView.constraints where constraint.debugDescription.contains("width == - 16") { subView.removeConstraint(constraint) } } } }
quelle
Sichere Lösung
Sie sollten die Einschränkung nicht entfernen, da sie in Zukunft mit einem korrekten Wert verwendet wird.
Alternativ können Sie die Konstante in einen positiven Wert ändern:
class PXAlertController: UIAlertController { override func viewDidLoad() { super.viewDidLoad() for subview in self.view.subviews { for constraint in subview.constraints { if constraint.firstAttribute == .width && constraint.constant == -16 { constraint.constant = 10 // Any positive value } } } } }
Und dann, um Ihren Controller zu initialisieren, verwenden Sie:
let controller = PXAlertController(title: "Title", message: "Message", preferredStyle: .actionSheet)
quelle
"<NSLayoutConstraint:0x28002b930 UIView:0x102e32420.width == - 16 (active)>"
. Ich kann nicht viel helfen, wenn ich Ihnen nicht sage, dass das Problem immer noch besteht. Wie jemand vorgeschlagen hat, werde ich den Fehler einfach ignorieren, aber ich mag es nicht.Eine alternative Möglichkeit, dem NSLayoutConstraint-Fehler zu entkommen, ist die Verwendung von
preferredStyle: .alert
anstelle vonpreferredStyle: .actionSheet
. Dies funktioniert ohne Generierung von Warnungen, zeigt das Menü jedoch modal an.quelle
Die Lösung für Objective-C:
Definieren Sie die Bereinigungsfunktion wie in der vorherigen Antwort
@implementation TemplateAlertController -(void) viewDidLoad { [super viewDidLoad]; [self mPruneNegativeWithConstraints]; } -(void) mPruneNegativeWithConstraints { for (UIView* iSubview in [self.view subviews]) { for (NSLayoutConstraint* iConstraint in [iSubview constraints]) { if ([iConstraint.debugDescription containsString:@"width == - 16"]) { [iSubview removeConstraint:iConstraint]; } } } } @end
quelle
Interessante Ideen hier. Persönlich mag ich die Idee nicht, die Einschränkung zu löschen oder ihren Wert (Größe) zu ändern.
Da das Problem davon abhängt, dass die Beschränkungsauflösung in eine Position gezwungen wird, in der eine vorgeschriebene Beschränkung (Priorität 1000) aufgehoben werden muss, besteht ein weniger brutaler Ansatz darin, dem Rahmen lediglich mitzuteilen, dass diese Beschränkung bei Bedarf aufgehoben werden könnte.
Also (basierend auf Joshs "Safe" -Klasse):
class PXAlertController: UIAlertController { override func viewDidLoad() { super.viewDidLoad() tweakProblemWidthConstraints() } func tweakProblemWidthConstraints() { for subView in self.view.subviews { for constraint in subView.constraints { // Identify the problem constraint // Check that it's priority 1000 - which is the cause of the conflict. if constraint.firstAttribute == .width && constraint.constant == -16 && constraint.priority.rawValue == 1000 { // Let the framework know it's okay to break this constraint constraint.priority = UILayoutPriority(rawValue: 999) } } } } }
Dies hat den Vorteil, dass es keine Layoutabmessungen ändert, und es besteht auch eine gute Chance, dass es sich im Falle einer Korrektur im Framework gut verhält.
Getestet im iPhone SE-Simulator (der mir mein ursprüngliches Problem bereitete) - das Debugging im Zusammenhang mit Einschränkungen ist weg.
quelle
Wenn Sie die Animation und alle Einschränkungen beibehalten möchten, sollten Sie eine negative Einschränkung finden und positiv machen, bevor Sie den Alert Controller präsentieren.
// Find negative constraint and make it positive for subview in alert.view.subviews { for constraint in subview.constraints { if constraint.constant < 0 { constraint.constant = -constraint.constant } } } // Present alert controller present(alert, animated: true)
quelle