Problème d'Autoresizing du cadre de UICollectionViewCell contentView dans la cellule prototype Storyboard (Xcode 6, SDK iOS 8) se produit lors de l'exécution sur iOS 7 uniquement

J'utilise Xcode 6 Beta 3, IOS 8 SDK. Construire la cible iOS 7.0 en utilisant Swift. Veuillez vous référer à mon problème étape par étape avec des captures d'écran ci-dessous.

J'ai un UICollectionView dans Storyboard. 1 Prototype UICollectionViewCell qui contient 1 étiquette au centre (pas de règle autoresizing). L'arrière-plan violet était de marquer un contentView qui est généré en cours d'exécution par la cellule, je suppose. Cette vue sera redimensionnée correctement sur mon UICollectionViewLayoutDelegate éventuellement, mais pas sur iOS 7. Avis que J'utilise Xcode 6 et le problème ne se produit que sur iOS 7.

Quand je construis l'application sur iOS 8. Tout est ok.

REMARQUE: Le violet est le contentView , Le Bleu est mon UIButton avec un coin arrondi.

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

Cependant, sur iOS 7, Toutes les sous-vues à l'intérieur de la cellule rétrécissent soudainement à la trame de (0,0,50,50) et ne se conforme plus à ma règle D'Autoresizing.

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

Je suppose que c'est un bug dans iOS 8 SDK ou Swift ou peut-être Xcode?


Mise À Jour 1: ce problème existe toujours dans le Xcode officiel 6.0.1 ! Le meilleur travail est comme ce que kocmohabta a suggéré ci-dessous en définissant le cadre dans cellForItem de la cellule (vous devez cependant sous-classer votre cellule). Il s'est avéré qu'il s'agit d'une incompatibilité entre iOS 8 SDK et iOS 7 (consultez la réponse d'ecotax ci-dessous Citée par Apple).

Mise à Jour 2: Collez ce code au début de votre cellForItem et les choses devraient être okay:

/** 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 **/
157
demandé sur halfer 2014-07-15 09:02:38

12 réponses

ContentView est cassé. Il peut également être corrigé dans awakeFromNib

ObjC:

- (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]
}
165
répondu Igor Palaguta 2018-10-03 08:46:50

J'ai rencontré le même problème et j'ai demandé de L'aide à Apple DTS. Leur réponse était:

Dans iOS 7, les vues de contenu des cellules se sont dimensionnées via autoresizing masque. Dans iOS 8, cela a été changé, les cellules ont cessé d'utiliser le autoresize masques et a commencé à dimensionner la vue de contenu dans layoutSubviews. Si une plume est encodée dans iOS 8, puis décodez-la sur iOS 7, vous aurez une vue de contenu sans un masque autoresizing et non d'autres moyens par lesquels se dimensionner. Donc, si jamais vous changez le cadre de la cellule, la vue de contenu ne suivra pas.

Les applications en cours de déploiement vers iOS 7 devront contourner ce problème en dimensionnement de la vue de contenu elle-même, ajout de masques contraintes.

Je suppose que cela signifie que ce n'est pas un bug dans XCode 6, mais une incompatibilité entre le SDK iOS 8 et le SDK iOS 7, qui vous frappera si vous passez à Xcode 6, car il commencera automatiquement à utiliser le SDK iOS 8.

Comme je l'ai déjà commenté, le solution de contournement Daniel Plamann décrit des travaux pour moi. Ceux décrits par Igor Palaguta et KoCMoHaBTa semblent plus simples, et semblent avoir du sens en donnant la réponse D'Apple DTS, donc je vais les essayer plus tard.

61
répondu ecotax 2014-09-17 07:34:06

J'ai rencontré le même problème et j'espère Qu'Apple va résoudre ce problème avec la prochaine version de Xcode. Pendant ce temps, j'utilise une solution de contournement. Dans ma sous-classe UICollectionViewCell, j'ai juste remplacé layoutSubviews et redimensionné le contentView manuellement au cas où la taille diffère de la taille collectionViewCell.

- (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
répondu Daniel Plamann 2014-09-23 07:34:47

Une autre solution consiste à définir la taille de contentView et les masques autoresizing dans -collectionView:cellForItemAtIndexPath: comme suit:

- (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;
}

Cela fonctionne aussi avec la mise en page automatique, car les masques de redimensionnement automatique sont traduits en contraintes.

38
répondu KoCMoHaBTa 2018-10-03 08:47:50

Dans Xcode 6.0.1 contentView pour UICollectionViewCell est cassé pour les appareils iOS7. Il peut également être corrigé en ajoutant des contraintes appropriées à UICollectionViewCell et à son contentView dans les méthodes awakeFromNib ou init.

        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
répondu SerJ_G 2014-10-15 14:06:18

Cela ne fonctionnera pas correctement sans les autres solutions de contournement mentionnées en raison d'un bug dans Xcode 6 GM avec la façon dont Xcode compile les fichiers xib au format nib. Bien que je ne puisse pas dire pour 100% de certitude que C'est lié à Xcode et ne pas avoir à faire avec l'exécution, je suis très confiant-voici comment je peux le Montrer:

  1. Construire + exécuter L'application dans Xcode 5.1.
  2. Allez dans le répertoire de l'application simulator et copiez le compilé .fichier nib pour le xib vous rencontrez des problèmes avec.
  3. Construire + exécuter L'application dans Xcode 6 GM.
  4. arrêtez l'application.
  5. Remplacer le.fichier nib dans le dossier simulateur de l'application nouvellement construite avec le.fichier nib créé à L'aide de Xcode 5.1
  6. relancez l'application depuis le simulateur, pas depuis Xcode.
  7. votre cellule chargée à partir de cela .nib devrait fonctionner comme prévu.

J'espère que tous ceux qui lisent cette question déposeront un Radar avec Apple. C'est un énorme problème et doit être résolu avant le Xcode final publier.

Edit: à la lumière du post de ecotax , je voulais juste mettre à jour ceci pour dire qu'il est maintenant confirmé les différences de comportement entre la construction dans iOS 8 vs iOS 7, mais pas un bug. Mon hack a corrigé le problème car la construction sur iOS 7 a ajouté le masque autoresizing à la vue de contenu nécessaire pour faire ce travail, ce que Apple n'ajoute plus.

4
répondu Acey 2017-05-23 12:18:08

Les réponses dans ce post fonctionnent, ce que je n'ai jamais compris est pourquoi {[29] } cela fonctionne.

Premièrement, il y a deux "règles":

  1. pour les vues créées par programme (ex. [UIView new]), la propriété translatesAutoresizingMaskIntoConstraints est définie sur YES
  2. Les vues créées dans Interface builder, avec AutoLayout activée, auront la propriété translatesAutoresizingMaskIntoConstraints définie sur NO

la deuxième règle ne semble pas s'appliquer aux vues de niveau supérieur pour lesquelles vous ne définissez pas de contraintes. (Ex. le voir le contenu)

Lorsque vous regardez une cellule de Storyboard, notez que la cellule n'a pas son contentView exposé. Nous ne sommes pas "contrôler" le contentView, Apple est.

Plongez profondément dans le code source du storyboard et voyez comment la cellule contentView est définie:

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

Maintenant, les sous-vues de la cellule (remarquez le translatesAutoresizingMaskIntoConstraints="NO"):

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

Le contentView n'a pas translatesAutoresizingMaskIntoConstraints défini sur NO. De plus, il manque de définition de mise en page, peut-être à cause de quoi @ ecotax dit.

Si nous regardons dans le contentView, il a un masque autoresizing, mais pas de définition pour cela: <autoresizingMask key="autoresizingMask"/>

Il y a Donc deux conclusions:

  1. contentView translatesAutoresizingMaskIntoConstraints est définie sur YES.
  2. contentView manque de définition d'une mise en page.

Cela nous amène à deux solutions dont on a parlé.

Vous pouvez définir manuellement les masques autoresizing dans awakeFromNib:

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

, Ou vous pouvez définir la contentView translatesAutoresizingMaskIntoConstraints de NO dans awakeFromNib et définir contraintes dans - (void)updateConstraints.

4
répondu kgaidis 2017-05-23 12:18:08

C'est la version rapide de la réponse de @Igor qui est acceptée et merci pour votre belle réponse mate.

Tout D'abord Allez dans votre sous-classe UICollectionViewCell et collez le code suivant tel qu'il se trouve dans la classe.

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

En passant, j'utilise Xcode 7.3.1 et Swift 2.3. La Solution est testée sur iOS 9.3 qui fonctionne parfaitement.

Merci, J'espère que cela a aidé.

4
répondu onCompletion 2016-06-15 18:59:58

Dans swift, placez le code suivant dans la sous-classe de cellule de vue de collection:

override var bounds: CGRect {
  didSet {
    // Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
    self.contentView.frame = bounds
  }
}
2
répondu Ian 2018-09-16 19:08:54

J'ai trouvé qu'il y avait aussi des problèmes avec le dimensionnement contentView dans iOS 8. Il a tendance à être mis en place très tard dans le cycle, ce qui peut provoquer des conflits de contraintes temporaires. Pour résoudre ce problème, j'ai ajouté la méthode suivante dans une catégorie de UICollectionViewCell:

- (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
}

Cette méthode doit être appelée après avoir désactivé la cellule.

1
répondu phatmann 2014-10-07 16:16:13

J'ai corrigé en faisant ceci:

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

Voir: ici

1
répondu Serluca 2017-05-23 12:34:21

Assurez-vous simplement de cocher la case "sous-vues Autoresize" dans la plume de cette cellule de vue de collection. Cela fonctionnera bien sur iOS 8 et iOS 7.

-1
répondu Deepak G M 2015-01-20 13:40:57