Soll die contentView.translatesAutoResizingMaskToConstraints einer UICollectionViewCell-Unterklasse auf "false" gesetzt werden?

TL; DR

Wenn Sie versuchen, die Größe von UICollectionViewCells über das automatische Layout zu ändern, können Sie auch anhand eines einfachen Beispiels Warnungen zum automatischen Layout erhalten.

Sollen wir @ setzcontentView.translatesAutoResizingMaskToConstraints = false Sie loswerden

Ich versuche, eine UICollectionView mit @ zu erstelleselbst Größe Auto-Layout-Zellen.

In viewDidLoad:

let layout = UICollectionViewFlowLayout()
layout.estimatedItemSize = CGSize(width: 10, height: 10)
collectionView.collectionViewLayout = layout

Meine Zelle ist sehr einfach. Es ist eine einzelne blaue Ansicht mit einer Breite und Höhe von 75 zu Testzwecken. Die Abhängigkeiten werden erstellt, indem die Ansicht an allen vier Kanten auf die Übersicht geklebt und mit einer Höhe und einer Breite versehen wird.

class MyCell: UICollectionViewCell {
  override init(frame: CGRect) {
    view = UIView()

    super.init(frame: frame)

    view.backgroundColor = UIColor.blueColor()
    contentView.addSubview(view)

    installConstraints()
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  var view: UIView

  func installConstraints() {
    view.translatesAutoresizingMaskIntoConstraints = false

    var c: NSLayoutConstraint

    // pin all edges
    c = NSLayoutConstraint(item: contentView, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1, constant: 0)
    c.active = true
    c = NSLayoutConstraint(item: contentView, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1, constant: 0)
    c.active = true
    c = NSLayoutConstraint(item: contentView, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 0)
    c.active = true
    c = NSLayoutConstraint(item: contentView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1, constant: 0)
    c.active = true

    // set width and height
    c = NSLayoutConstraint(item: view, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 75)
    c.active = true
    c = NSLayoutConstraint(item: view, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 75)
    c.active = true
  }
}

Beim Ausführen des Codes erhalte ich zwei Fehler, weil ich Einschränkungen nicht gleichzeitig erfüllen kann:

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:0x7fed88c1bac0 h=--& v=--& H:[UIView:0x7fed8a90c2f0(10)]>",
    "<NSLayoutConstraint:0x7fed8ab770b0 H:[UIView:0x7fed8a90bbe0(75)]>",
    "<NSLayoutConstraint:0x7fed8a90d610 UIView:0x7fed8a90c2f0.leading == UIView:0x7fed8a90bbe0.leading>",
    "<NSLayoutConstraint:0x7fed8ab005f0 H:[UIView:0x7fed8a90bbe0]-(0)-|   (Names: '|':UIView:0x7fed8a90c2f0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fed8ab770b0 H:[UIView:0x7fed8a90bbe0(75)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

(Der zweite Fehler in Bezug auf die vertikalen Einschränkungen wird weggelassen, ist jedoch nahezu identisch.)

Diese Fehler sind sinnvoll. Im Wesentlichen ist die contentView 0x7fed8a90c2f0) hattranslatesAutoresizingMask = true, so dass seine Grenzen auf 10x10 (ausgehend von der geschätzten Größe) gesetzt werden, dassNSAutoresizingMaskLayoutConstraint Einschränkung. Es gibt keine Möglichkeit, dass die Ansicht sowohl 10 Pixel als auch 75 Pixel breit sein kann. Daher wird ein Fehler ausgegeben.

Ich habe verschiedene Dinge versucht, um dieses Problem zu lösen. Nur zwei davon scheinen zu funktionieren.

Lösung 1: Setzen Sie mindestens eine der Einschränkungen auf 999 oder weniger

In diesem Fall wird das Problem behoben, wenn ich die Einschränkung, die den unteren Rand der blauen Ansicht mit dem unteren Rand der contentView verbindet, auf die Priorität 999 ändere (und das Gleiche mit der nachfolgenden Einschränkung tue). Ebenso hätte ich Top + Leading oder Width + Height wählen können, solange ich nicht 1000 Prioritäten in jede Richtung habe. Mindestens eine muss für das anfängliche Layout "geben".

Auch wenn es so klingt, als ob die Ansicht eine falsche Höhe / Breite hätte, scheint es tatsächlich die richtige Größe zu haben.

Lösung 2: SetzecontentView.translatesAutoresizingMaskIntoConstraints = false

Mit dieser Einstellung auffalse, es wird im Wesentlichen der @ lNSAutoresizingMaskLayoutConstraint Constraint, und wir haben keinen Konflikt mehr. Auf der anderen Seite ist es so, als würde die Übersicht (die Zelle) niemals ihre Größe aktualisieren, da die Inhaltsansicht zu Beginn nicht mit automatischem Layout eingerichtet ist, da nichts "drängt". zurück dagegen.

rotzdem funktioniert diese Lösung auf magische Weise. Ich gehe davon aus, dass die Zelle irgendwann auf den Frame von contentView schaut und entscheidet, dass "Hey, Sie haben mich auf diese Größe eingestellt, das heißt, Sie möchten, dass die Zelle auch diese Größe hat", und kümmert sich darum, die Größe der Zelle für Sie zu ändern.

Welche Lösung sollten wir verwenden?

Gibt es bessere Lösungen für dieses Problem? Welches der oben genannten sollte verwendet werden? Gibt es Nachteile der beiden oben genannten Lösungen oder sind sie im Wesentlichen gleich und es spielt keine Rolle, welche Sie verwenden?

Anmerkungen

Der Grund, warum es schwieriger ist, in Beispielen wie @ zu seh DGSelfSizingCollectionViewCells ist, weil sie sich auf intrinsicContentSize + contentCompressionResistancePriority verlassen. Wenn Sie meine Einschränkungen für Breite und Höhe aufheben, sie durch 1000 setContentCompressionResistancePriority-Aufrufe (horizontal + vertikal) ersetzen und etwas mit einer bestimmten Größe (z. B. eine Beschriftung mit Text) verwenden, werden die automatischen Layoutfehler nicht mehr angezeigt. Dies impliziert, dasswidth@1000 verhältander als ein intrinsicWidth +contentCompressionResistance@1000. Vielleicht ist die Zeit, zu der eine Ansicht ihre intrinsische Breite erhält, nachdem es in Ordnung ist, den Rahmen der Inhaltsansicht zu ändern.

Dinge die nicht funktionierten:

Mir ist aufgefallen, dass ich beim Erstellen von Zellen über ein Storyboard normalerweise nie auf dieses Problem gestoßen bin. Als ich die Unterschiede imview einer Zelle, die über ein Storyboard und eine programmgesteuert erstellte Zelle erstellt wurde, ist mir aufgefallen, dass dasautoresizingMask war RM + BM (36) im Storyboard, aber 0, wenn es über Code erstellt wurde. Ich habe versucht, das @ manuell einzustellautoresizingMask von meinem blauen blick auf 36, aber das hat nicht funktioniert. Der eigentliche Grund, warum die Storyboard-Lösung funktioniert, ist, dass die von Ihnen erstellten Einschränkungen normalerweise bereits perfekt im Storyboard festgelegt sind (andernfalls würden Storyboard-Fehler auftreten, die behoben werden müssen). Im Rahmen der Behebung dieser Fehler können Sie die Grenzen der Zelle ändern. Da ruft esinit?(coder:), die Grenzen der Zelle sind bereits korrekt konfiguriert. Also obwohl dascontentView.autoresizingMask = true, es gibt keine Konflikte, da es bereits in der richtigen Größe definiert ist.In der verlinkten Anleitung wird auf @ verwiesedieser Beitra wenn es um das Erstellen von Einschränkungen geht. Es wird erwähnt, dass Einschränkungen in @ erstellt werden sollteupdateConstraints. Es hört sich jedoch so an, als ob dies Apples ursprüngliche Empfehlungen waren und dass sienicht mehr empfehlen diese Konvention für die meisten Ihrer Einschränkungen. Trotzdem, da dieser Artikel sagt, sie in @ zu erstellupdateConstraints Ich habe erfolglos versucht. Ich habe die gleichen Ergebnisse erzielt. Dies liegt daran, dass der Frame zum Zeitpunkt des Aufrufs von updateConstraints nicht aktualisiert wurde (es war immer noch 10x10). Ich habe ähnliche Probleme festgestellt, wenn Sie eine zu kleine geschätzte Größe gewählt haben. Ich habe es in der Vergangenheit durch Erhöhen der geschätzten Größe behoben. In diesem Fall habe ich versucht, 100x100, aber es verursacht immer noch die gleichen Fehler. Das macht Sinn ... eine Ansicht kann nicht gleichzeitig 100 und 75 breit sein. (Beachten Sie, dass ich die Einstellung 75x75 für eine Nicht-Lösung halte. Weitere Informationen finden Sie weiter unten.)

Nicht-Lösungen:

Stellen Sie die geschätzte Größe auf 75x75 ein. Dadurch werden zwar die Fehler in diesem einfachen Beispiel behoben, das Problem mit Zellen, deren Größe wirklich dynamisch ist, wird jedoch nicht behoben. Ich möchte eine Lösung, die überall funktioniert.Die genauen Abmessungen der Zelle in @ zurückgebcollectionView(_:layout:sizeForItemAtIndexPath:) (z. B. durch Erstellen einer Größenzelle). Ich möchte eine Lösung, die direkt mit meinem Handy funktioniert, ohne dass Buchhaltung oder zusätzliche Berechnungen erforderlich sind.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage