Meine Layoutbeschränkungen sind in Interface Builder in Ordnung, aber zur Laufzeit tritt eine Ausnahme auf, da ein Teil des Frameworks feste Höhen- und Breitenbeschränkungen anwendet, die ich wirklich nicht möchte. Warum sind sie dort und wie können sie ausgeschaltet werden?
Dies sind die letzten beiden Einschränkungen, die in der protokollierten Liste angezeigt werden:
2014-04-26 09:02:58.687 BBCNews[32058:60b] 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:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width>",
"<NSLayoutConstraint:0xbf47190 UIView:0xbf4a3c0.leading == BNMyNewsCell_landscape:0xbf48b10.leading>",
"<NSLayoutConstraint:0xbf47160 UIView:0xbf4a3c0.trailing == BNMyNewsCell_landscape:0xbf48b10.trailing>",
"<NSLayoutConstraint:0xbf47130 BNMyNewsCell_landscape:0xbf48b10.bottom == UIView:0xbf4a3c0.bottom>",
"<NSLayoutConstraint:0xbf47100 UIView:0xbf4a3c0.top == BNMyNewsCell_landscape:0xbf48b10.top>",
"<NSLayoutConstraint:0xd4c3c40 'UIView-Encapsulated-Layout-Width' H:[BNMyNewsCell_landscape:0xbf48b10(304)]>",
"<NSLayoutConstraint:0xd4c38a0 'UIView-Encapsulated-Layout-Height' V:[BNMyNewsCell_landscape:0xbf48b10(290)]>"
}
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width>
quelle
UIView-Encapsulated-Layout-Width
Um dies hinzuzufügen, hatte ich ein ähnliches Problem mit dem 8.3-Gerät und erinnerte mich an diesen Tweet . Das Anrufen[someView layoutIfNeeded]
half, das Problem zu beheben.Dies kann Ihre Frage nicht beantworten, aber es könnte anderen wie mir helfen, die von der Suche hierher gekommen sind.
Ich habe einen seltsamen Fehler bei einer fehlerhaften AutoLayout-Einschränkung erhalten, der von einer
UIView-Encapsulated-Layout-Width
Einschränkung begleitet wurde , weil ichtableHeaderView
einer Tabellenansicht eine hinzugefügt habe, deren Größe noch nicht mit AutoLayout festgelegt wurde. Das System hat also versucht, die Einschränkungen meiner Header-Unteransichten in einer Tabellenansicht mit einem Frame von anzuwenden{0,0,0,0}
. Da UITableView die Kontrolle über die Breite seiner Elemente mag, wurde die generierte BreitenbeschränkungUIView-Encapsulated-Layout-Width
auf Null gesetzt, was zu allerlei Verwirrung mit meinen Header-Elementen führte, die eine Breite von 320 + pt erwarteten.Zum Mitnehmen: Stellen Sie sicher, dass Sie Ihre Zusatz- / Kopf- / Fußzeilenansichten hinzufügen / bearbeiten, nachdem die Tabellenansicht von AutoLayout angepasst wurde.
quelle
[thatContainer layoutIfNeeded]
bevor Sie die Einschränkungen für die Unteransicht festlegen. Wenn Sie den Fehler nicht erhalten und Ihre Ansichten klar sind, brauchen Sie sich keine Sorgen zu machen.Ich war mit der gleichen seltsamen Einschränkung konfrontiert und hatte keine Ahnung warum, bis ich mich an das verdammte
translatesAutoresizingMaskIntoConstraints
Eigentum erinnerte. Stellen Sie dies ein, umfalse
das Problem zu lösen. Im Hintergrund werden die Masken für die automatische Größenänderung (die alte Layout-Engine für iOS) in Einschränkungen konvertiert. Sehr oft möchten Sie diese Einschränkungen nicht und möchten Ihre eigenen. In solchen Fällen sollten Sie diese Eigenschaft auf false setzen, und es wird Ihnen gut gehen:view.translatesAutoresizingMaskIntoConstraints = false
quelle
view
stellst du das genau ein? Ist es UITableViewCell?Auf jeden Fall auf a
UITableView
's zu sehentableHeaderView
. Ich konnte dies mit einer benutzerdefinierten Header-Ansicht zum Laufen bringen, indem ich die Breite explizit auf die BreitetableView
nach dem Festlegen von einstelltetableHeaderView
und sie dann nach Abschluss eines Layout-Durchlaufs zurücksetzte.Beispielcode für iOS 9, bei dem davon ausgegangen wird, dass Sie eine
UITableView
Methode alstableView
und ein Element zum Konfigurieren alsitem
: übergeben haben.//Create the header view self.contentDetailHeaderView = MyCustomHeaderView() //Turn on autolayout self.contentDetailHeaderView.translatesAutoresizingMaskIntoConstraints = false //Add the header to the table view tableView.tableHeaderView = self.contentDetailHeaderView //Pin the width let widthConstraint = NSLayoutConstraint(item: self.contentDetailHeaderView, attribute: .Width, relatedBy: .Equal, toItem: tableView, attribute: .Width, multiplier: 1, constant: 0) tableView.addConstraint(widthConstraint) //Do whatever configuration you need to - this is just a convenience method I wrote on my header view. self.contentDetailHeaderView.setupForItem(item) //Lay out the configured view self.contentDetailHeaderView.layoutIfNeeded() //Reset the table header view, because ¯\_(ツ)_/¯ tableView.tableHeaderView = self.contentDetailHeaderView
Ein paar Notizen, vor allem, wenn ich das noch einmal nachschaue, weil ich die Erinnerung an einen Goldfisch habe:
viewDidLayoutSubviews
- ich konnte diese Technik verwenden, solange dietableView
während des Setups die entsprechende Breite hat..xib
und dann sichergestellt, dass alle Elemente angeheftet sind, sodass die Höhe aktualisiert wird, wenn sich die Breite der Ansicht ändert.viewForHeaderInSection
, ist es wahrscheinlich besser, sich etwas außerhalb des Bildschirms zu schnappen, das Sie nach dieser Technik auslegen können . Ich hatte nicht viel Glück mit den selbstleimenden Teilen.quelle
In iOS 11 treten unzählige Layoutkonflikte auf, die Verweise auf diese Einschränkungen enthalten und tatsächlich über das
translatesAutoresizingMaskIntoConstraints
Flag hinzugefügt werden . Es scheint, dass in iOS 11 viel mehr AutoLayout-Magie auftritt, wenn eine Ansicht zur Hierarchie hinzugefügt wird, als nur, wenn die Ansicht angelegt ist (wie es in früheren iOS-Versionen zu funktionieren schien).Dies ist der Fall, auf den wir gestoßen sind:
Der zweite Schritt (***) führt zu einem Konflikt, da das System der Ansicht zum Zeitpunkt des Hinzufügens der Ansicht zur Hierarchie Größenbeschränkungen von Null hinzufügt. Wir haben die Einstellung
translatesAutoresizingMaskIntoConstraints
später vorgenommen, weil wir das PureLayout-Framework verwendet haben, das dieses Flag automatisch korrekt setzt, wenn Sie die Ansicht einschränken. In iOS 11 müssen Sie jedoch daran denken, dietranslatesAutoresizingMaskIntoConstraints
Erstellung zum Zeitpunkt der Erstellung zu deaktivieren , bevor die Ansicht zum hinzugefügt wird Hierarchie.Ich vermute, Apple dachte, dass es weitaus hilfreicher als schmerzhaft wäre, dieses Flag auf JA zu setzen. Dies war leider nicht der Fall.
quelle
initForAutoLayout
undnewAutoLayoutView
Initialisierer, dietranslatesAutoresizingMaskIntoConstraints
auf false gesetzt sind und in ALView-Unterklassen aufgerufen werden könnenIch habe diesen Fehler unter allen möglichen Umständen erhalten (nicht unbedingt an UICollectionView und Freunde gebunden, wie in der richtigen Antwort hier vorgeschlagen).
Meine Art, damit umzugehen, bestand darin, einfach alle Einschränkungen zu löschen und sie dann wieder aufzubauen (nur dieses Mal habe ich keine Angst davor, dass meine Einschränkungen mit diesen vorab erstellten kollidieren):
also im Code:
UIView *parentView = [viewInQuestion superview]; [parentView clearConstraintsOfSubview:viewInQuestion];
Wo
clearConstraintsOfSubview
ist eine Kategoriemethode in UIView:- (void)clearConstraintsOfSubview:(UIView *)subview { for (NSLayoutConstraint *constraint in [self constraints]) { if ([[constraint firstItem] isEqual:subview] || [[constraint secondItem] isEqual:subview]) { [self removeConstraint:constraint]; } } }
quelle
Ich hatte ein ähnliches Problem und löste es wie folgt.
Umgebung: Swift 5.0, xcode 10.2.1, Ansichten programmgesteuert einstellen
Warnmeldung: Einschränkungen können nicht gleichzeitig erfüllt werden ... 'UIView-Encapsulated-Layout-Width' UIView: 0x0000000000.width == 0 (aktiv)> ")
Code mit Warnung
override func loadView() { view = UIView() /// Adds the subviews to the view and sets their properties and constraints setupViews() }
Code, der die Warnung löschte
override func loadView() { /// Needed to set the frame of the root view to the window frame. let window = UIWindow() view = UIView(frame: window.frame) /// Adds the subviews to the view and sets their properties and constraints setupViews() }
Hinweise zur loadView () -Methode: "Wenn Sie Ihre Ansichten mit Interface Builder erstellen und den Ansichtscontroller initialisieren, dürfen Sie diese Methode nicht überschreiben. Sie können diese Methode überschreiben, um Ihre Ansichten manuell zu erstellen. Wenn Sie dies möchten Weisen Sie der Ansichtseigenschaft die Stammansicht Ihrer Ansichtshierarchie zu. Die von Ihnen erstellten Ansichten sollten eindeutige Instanzen sein und nicht mit anderen View-Controller-Objekten geteilt werden. Ihre benutzerdefinierte Implementierung dieser Methode sollte nicht super aufrufen. " - Apple-Dokumentation
Hinweise zur Stammansicht:
"Wenn Sie Ansichten lieber programmgesteuert erstellen möchten, überschreiben Sie dazu die loadView-Methode Ihres View-Controllers. Ihre Implementierung dieser Methode sollte Folgendes bewirken:
Erstellen Sie ein Stammansichtsobjekt. Die Stammansicht enthält alle anderen Ansichten, die Ihrem Ansichtscontroller zugeordnet sind. Normalerweise definieren Sie den Rahmen für diese Ansicht so, dass er der Größe des App-Fensters entspricht, das selbst den Bildschirm ausfüllen soll. Der Rahmen wird jedoch basierend auf der Anzeige Ihres View Controllers angepasst. Siehe "Ändern der Größe der Controller-Ansicht".
Sie können ein generisches UIView-Objekt, eine von Ihnen definierte benutzerdefinierte Ansicht oder eine andere Ansicht verwenden, die skaliert werden kann, um den Bildschirm auszufüllen.
Erstellen Sie zusätzliche Unteransichten und fügen Sie sie der Stammansicht hinzu. "- Alte Apfeldokumentation?
quelle
Nachdem ich eine Weile mit dem Kopf geschlagen hatte, fand ich diesen Link . In meinem Fall passierte es in der UITableViewHeaderFooterView, als ich insertRows oder deleteRows von meinem UIVieController verwendete. 'EstimatedSectionHeaderHeight' und 'EstimatedRowHeight' wurden gesetzt, meine Einschränkungen wurden dreimal wiederholt ... Der angezeigte Fehler war:
"<NSLayoutConstraint:0x280648140 H:|-(8)-[UIImageView:0x106e94860] (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>", "<NSLayoutConstraint:0x280648230 H:[UIImageView:0x106e94860]-(8)-[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...'] (active)>", "<NSLayoutConstraint:0x280648410 H:[UIButton:0x106ea5a40]-(8)-| (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>", "<NSLayoutConstraint:0x280648460 H:[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...']-(8)-[UIButton:0x106ea5a40] (active)>", "<NSLayoutConstraint:0x2806493b0 'UIView-Encapsulated-Layout-Width' DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50.width == 0 (active)>"
Wie auf dem Link angegeben:
" Wenn Sie mit bestimmten Animationstypen Zeilen einfügen oder löschen löschen, animiert UIKit die Zeilenhöhe von 0 auf volle Höhe oder zurück. Am 0-Ende dieser Animation können die Layoutgleichungen nicht gelöst werden, wenn die gesamte vertikale Achse auf Priorität gesetzt ist = 1000. Aber senken Sie nur eine Einschränkung auf 999 - sagen Sie, dass der untere Bereich zum Überwachen des Randes - und alles ist in Ordnung; der Inhalt wird nur außerhalb der Grenzen der Zelle abgelegt. "
Die Lösung bestand darin, die führende Priorität von UIImageView auf 999 (oder niedriger auf 1000) zu setzen.
quelle
In meinem Fall habe ich versehentlich zweimal meine programmatischen Einschränkungen festgelegt. Sobald ich den doppelten Anruf entfernt hatte, verschwanden die Konflikte.
quelle
Ich habe dieses Problem festgestellt, wenn ich AL create tableviewHeader verwende
Ich initiiere die Tabellenansicht wie unten
let table = UITableView.init(frame: .zero, style: .grouped) // set table constraint ...
dann erstelle ich tableviewHeader mit AutoLayout.
"<NSLayoutConstraint:0x600003d7d130 'UIView-Encapsulated-Layout-Width' UIView:0x7fe92bc55260.width == 0 (active)>"
Es wird ein symbolischer Haltepunkt angezeigt
Nachdem ich @Yerk verwiesen habe, ist die Antwort. Ich ändere den Frame, wenn ich tableView initiiere
let rect = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: 0) let table = UITableView.init(frame:rect , style: .grouped)
Das Problem scheint gelöst zu sein
quelle
Endlich habe ich eine Lösung für CollectionView gefunden! Wenn Sie wie ich storyBoard verwenden, wird es Ihnen helfen!
Interface Builder / Storyboard
Gehen Sie zu storyBoard -> wählen Sie Ihre CollectionView aus. ScreenShot CollectionView Gehen Sie zum Größeninspektor und setzen Sie die geschätzte Größe auf Keine ScreenShot Schätzgröße
Das ist alles!
quelle
Beim Testen von Split View auf dem iPad Pro wurde ein ähnliches Problem festgestellt, und die Antwort von DesignatedNerd funktionierte, aber ich brauchte nicht so viel Code. Folgendes habe ich verwendet:
[self.tableView.tableHeaderView setTranslatesAutoresizingMaskIntoConstraints:NO]; NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.tableView attribute:NSLayoutAttributeWidth multiplier:1 constant:0]; NSLayoutConstraint *yConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.tableView attribute:NSLayoutAttributeTop multiplier:1 constant:0]; [self.tableView addConstraints:@[widthConstraint, yConstraint]];
Beachten Sie das Hinzufügen der Y-Einschränkung, die den oberen Rand der tableHeaderView an den oberen Rand der tableView bindet.
quelle
Ich hatte das gleiche Problem beim Hinzufügen von Einschränkungen zu einem Tabellenansichts-Header. Es scheint aufzutreten, wenn Einschränkungen mit festgelegten Konstanten hinzugefügt werden, wenn die Grenzen des Headers (0,0,0,0) waren. Ich habe es geschafft, dies zu beheben, indem ich die Einschränkungen in der Layout-Unteransichtsmethode nur hinzugefügt habe, wenn die Grenzen des Headers nicht (0,0,0,0) waren.
if self.bounds == CGRect.zero { return }
quelle
Die Einschränkung
UIView-Encapsulated-Layout-Height
wird mit dem von Ihnen festgelegten Wert erstellttableView.estimatedSectionHeaderHeight
quelle