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.
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.
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 **/
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]
}
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.
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;
}
}
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.
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)]];
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:
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.
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.
Die Antworten in diesem Beitrag funktionieren, was ich nie verstanden habe, ist warum es funktioniert.
Erstens gibt es zwei "Regeln":
[UIView new]
), Wird die Eigenschaft translatesAutoresizingMaskIntoConstraints
auf YES
gesetzt.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:
contentView
translatesAutoresizingMaskIntoConstraints
wird auf YES
gesetzt.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 contentView
translatesAutoresizingMaskIntoConstraints
in NO
auf awakeFromNib
setzen und Einschränkungen in - (void)updateConstraints
definieren.
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
}
}
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.
Ich habe Folgendes behoben:
override func layoutSubviews() {
contentView.superview?.frame = bounds
super.layoutSubviews()
}
siehe: hier