webentwicklung-frage-antwort-db.com.de

Das Problem der automatischen Größenänderung von UICollectionViewCell contentView in der Storyboard-Prototypzelle (Xcode 6, iOS 8 SDK) tritt nur unter iOS 7 auf

Ich verwende Xcode 6 Beta 3, iOS 8 SDK. Erstellen Sie das Ziel iOS 7.0 mit Swift. Bitte beziehen Sie sich auf mein Problem Schritt für Schritt mit Screenshots unten.

Ich habe eine UICollectionView im Storyboard. 1 UICollectionViewCell-Prototyp, der 1 Etikett in der Mitte enthält (keine Regel für die automatische Größenänderung). Der violette Hintergrund sollte eine Inhaltsansicht markieren, die zur Laufzeit von der Zelle generiert wird. Die Größe dieser Ansicht wird basierend auf meiner UICollectionViewLayoutDelegate-Version angepasst, jedoch nicht auf iOS 7. Beachten Sie, dass ich Xcode 6 verwende und das Problem nur auf iOS 7 auftritt.

Wenn ich die App auf iOS 8 erstelle. Alles ist in Ordnung.

Hinweis: Lila ist das contentView , Blau ist mein UIButton mit abgerundeter Ecke.

http://i.stack.imgur.com/uDNDY.png

Unter iOS 7 schrumpfen jedoch alle Unteransichten in der Zelle plötzlich auf den Wert (0,0,50,50) und entsprechen nie mehr meiner Autoresizing-Regel.

http://i.stack.imgur.com/lOZH9.png

Ich nehme an, dies ist ein Fehler in iOS 8 SDK oder Swift oder vielleicht Xcode?


pdate 1: Dieses Problem existiert noch im offiziellen Xcode 6.0.1! Die beste Lösung ist die, die KoCMoHaBTa unten vorgeschlagen hat, indem Sie den Rahmen in cellForItem der Zelle festlegen (Sie müssen Ihre Zelle jedoch in Unterklassen unterteilen). Es stellte sich heraus, dass dies eine Inkompatibilität zwischen iOS 8 SDK und iOS 7 ist (siehe die Antwort von ecotax unten, zitiert von Apple).

pdate 2: Fügen Sie diesen Code zu Beginn Ihres cellForItem ein und alles sollte in Ordnung sein:

/** Xcode 6 on iOS 7 hot fix **/
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
/** End of Xcode 6 on iOS 7 hot fix **/
158
thkeen

contentView ist fehlerhaft. Es kann auch in awakeFromNib behoben werden

Objekt:

- (void)awakeFromNib {

    [super awakeFromNib];

    self.contentView.frame = self.bounds;
    self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}

Swift3:

override func awakeFromNib() {
    super.awakeFromNib()

    self.contentView.frame = self.bounds
    self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
169
Igor Palaguta

Ich bin auf dasselbe Problem gestoßen und habe Apple DTS um Hilfe gebeten. Ihre Antwort lautete:

In iOS 7 wurde die Größe der Inhaltsansichten von Zellen mithilfe von Masken für die automatische Größenänderung angepasst. In iOS 8 wurde dies geändert, Zellen verwendeten keine Autoresizing-Masken mehr und begannen, die Größe der Inhaltsansicht in layoutSubviews zu ändern. Wenn eine Schreibfeder in iOS 8 codiert und dann in iOS 7 decodiert wird, haben Sie eine Inhaltsansicht ohne automatische Größenanpassung und keine andere Möglichkeit, die Größe selbst festzulegen. Wenn Sie also jemals den Rahmen der Zelle ändern, folgt die Inhaltsansicht nicht.

Apps, die auf iOS 7 zurückgesetzt werden, müssen dies umgehen, indem sie die Größe der Inhaltsansicht selbst anpassen, automatische Größenänderungsmasken hinzufügen oder Einschränkungen hinzufügen.

Ich vermute, dies bedeutet, dass es sich nicht um einen Fehler in XCode 6 handelt, sondern um eine Inkompatibilität zwischen iOS 8 SDK und iOS 7 SDK, die Sie bei einem Upgrade auf Xcode 6 trifft, da das iOS 8 SDK automatisch verwendet wird.

Wie bereits erwähnt, funktioniert die von Daniel Plamann beschriebene Problemumgehung für mich. Die von Igor Palaguta und KoCMoHaBTa beschriebenen sehen jedoch einfacher aus und scheinen eine sinnvolle Antwort auf die Frage Apple DTS) zu geben. Ich werde sie später versuchen.

61
ecotax

Ich bin auf dasselbe Problem gestoßen und hoffe, dass Apple mit der nächsten Xcode-Version behoben wird. In der Zwischenzeit verwende ich eine Problemumgehung. In meiner UICollectionViewCell -Unterklasse habe ich layoutSubviews und ändern Sie die Größe der Inhaltsansicht manuell, falls die Größe von der Größe von collectionViewCell abweicht.

- (void)layoutSubviews
{
  [super layoutSubviews];

  BOOL contentViewIsAutoresized = CGSizeEqualToSize(self.frame.size, self.contentView.frame.size);

  if( !contentViewIsAutoresized) {
    CGRect contentViewFrame = self.contentView.frame;
    contentViewFrame.size = self.frame.size;
    self.contentView.frame = contentViewFrame;
  }
}
60
Daniel Plamann

Eine andere Lösung besteht darin, die Größe und die Autoresizing-Masken von contentView in -collectionView:cellForItemAtIndexPath: Wie folgt festzulegen:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

     static NSString *cellID = @"CellID";

     UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

     // Set contentView's frame and autoresizingMask
     cell.contentView.frame = cell.bounds;
     cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;

     // Your custom code goes here

     return cell;
}

Dies funktioniert auch mit dem automatischen Layout, da Masken zur automatischen Größenänderung in Einschränkungen übersetzt werden.

38
KoCMoHaBTa

In Xcode 6.0.1 ist contentView für UICollectionViewCell für iOS7-Geräte fehlerhaft. Sie kann auch behoben werden, indem Sie UICollectionViewCell und dessen contentView in awakeFromNib- oder init-Methoden geeignete Einschränkungen hinzufügen.

        UIView *cellContentView = self.contentView;
        cellContentView.translatesAutoresizingMaskIntoConstraints = NO;

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[cellContentView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(cellContentView)]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[cellContentView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(cellContentView)]];
6
SerJ_G

Ohne eine der anderen genannten Problemumgehungen funktioniert dies aufgrund eines Fehlers in Xcode 6 GM beim Kompilieren von xib-Dateien im nib-Format nicht ordnungsgemäß. Ich kann zwar nicht mit hundertprozentiger Gewissheit sagen, dass es sich um Xcode handelt und dass es sich nicht um Laufzeit handelt, aber ich bin sehr zuversichtlich - so kann ich es zeigen:

  1. Erstellen + Starten Sie die Anwendung in Xcode 5.1.
  2. Wechseln Sie in das Verzeichnis der Simulatoranwendung und kopieren Sie die kompilierte .nib-Datei für die xib, mit der Sie Probleme haben.
  3. Erstellen + Starten Sie die Anwendung in Xcode 6 GM.
  4. Beenden Sie die Anwendung.
  5. Ersetzen Sie die NIB-Datei im Simulatorordner der neu erstellten Anwendung durch die mit Xcode 5.1 erstellte NIB-Datei
  6. Starten Sie die App vom Simulator aus neu, NICHT von Xcode.
  7. Ihre von dieser .nib geladene Zelle sollte wie erwartet funktionieren.

Ich hoffe, dass jeder, der diese Frage liest, einen Radar bei Apple einreicht. Dies ist ein RIESIGES Problem und muss vor der endgültigen Xcode-Veröffentlichung behoben werden.

Edit: Im Lichte von ecotax's post wollte ich dies nur aktualisieren, um zu sagen, dass es jetzt bestätigte Verhaltensunterschiede zwischen iOS 8 und iOS 7 gibt, aber kein Fehler. Mein Hack hat das Problem behoben, da die Autoresizing-Maske in iOS 7 der Inhaltsansicht hinzugefügt wurde, die für diese Funktion erforderlich ist. Dies wird von Apple nicht mehr hinzugefügt.

4
Acey

Dies ist die Swift Version von @ Igors Antwort, die akzeptiert wird, und vielen Dank für Ihren netten Antwortkameraden.

Zuerst Gehe zu deiner UICollectionViewCell Unterklasse und füge den folgenden Code so ein, wie er sich in der Klasse befindet.

override func awakeFromNib() {
    super.awakeFromNib()
    self.contentView.frame = self.bounds
    self.contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
}

Übrigens benutze ich Xcode 7.3.1 und Swift 2.3. Die Lösung wurde unter iOS 9.3 getestet und funktioniert einwandfrei.

Danke, hoffe das hat geholfen.

4
onCompletion

Die Antworten in diesem Beitrag funktionieren, was ich nie verstanden habe, ist warum es funktioniert.

Erstens gibt es zwei "Regeln":

  1. Für Ansichten, die programmgesteuert erstellt wurden (Beispiel: [UIView new]), Wird die Eigenschaft translatesAutoresizingMaskIntoConstraints auf YES gesetzt.
  2. In Ansichten, die mit aktiviertem AutoLayout im Interface Builder erstellt wurden, ist die Eigenschaft translatesAutoresizingMaskIntoConstraints auf NO gesetzt.

Die zweite Regel scheint nicht für Ansichten der obersten Ebene zu gelten, für die Sie keine Einschränkungen definieren. (Bsp. Die Inhaltsansicht)

Beachten Sie beim Betrachten einer Storyboard-Zelle, dass für die Zelle die contentView nicht verfügbar ist. Wir "kontrollieren" nicht die contentView, Apple ist.

Tauchen Sie tief in den Storyboard-Quellcode ein und sehen Sie, wie die Zelle contentView definiert ist:

<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">

Nun die Subviews der Zelle (beachte den translatesAutoresizingMaskIntoConstraints="NO"):

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NaT-qJ-npL" userLabel="myCustomLabel">

Für contentView ist translatesAutoresizingMaskIntoConstraints nicht auf NO festgelegt. Plus es fehlt Layout-Definition, vielleicht wegen was @ ecotax sagte .

Wenn wir uns die contentView ansehen, gibt es eine Autoresizing-Maske, aber keine Definition dafür: <autoresizingMask key="autoresizingMask"/>

Es gibt also zwei Schlussfolgerungen:

  1. contentViewtranslatesAutoresizingMaskIntoConstraints wird auf YES gesetzt.
  2. contentView fehlt die Definition eines Layouts.

Dies führt uns zu zwei Lösungen, über die gesprochen wurde.

Sie können die Autoresizing-Masken manuell in awakeFromNib einstellen:

self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Oder Sie können contentViewtranslatesAutoresizingMaskIntoConstraints in NO auf awakeFromNib setzen und Einschränkungen in - (void)updateConstraints definieren.

4
kgaidis

Fügen Sie in Swift den folgenden Code in die Zellenunterklasse der Sammlungsansicht ein:

override var bounds: CGRect {
  didSet {
    // Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
    self.contentView.frame = bounds
  }
}
2
Ian

Ich habe festgestellt, dass es auch Probleme mit der Größe von contentView in iOS 8 gibt. Es wird in der Regel sehr spät im Zyklus ausgelegt, was zu vorübergehenden Einschränkungen führen kann. Um dies zu lösen, habe ich die folgende Methode in eine Kategorie von UICollectionViewCell eingefügt:

- (void)fixupContentView
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80100
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
        self.contentView.frame = self.bounds;
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    } else {
        [self layoutIfNeeded];
    }
#endif
#endif
}

Diese Methode sollte nach dem Ausreihen der Zelle aufgerufen werden.

1
phatmann

Ich habe Folgendes behoben:

override func layoutSubviews() {
   contentView.superview?.frame = bounds
   super.layoutSubviews()
}

siehe: hier

1
Serluca