Problema de restricciones de diseño automático en iOS7 en UITableViewCell
autolayout nslayoutconstraint (10)
Estoy usando restricciones de diseño automático programáticamente para diseñar mis celdas UITableView personalizadas y estoy definiendo correctamente los tamaños de celda en tableView:heightForRowAtIndexPath:
Está funcionando bien en iOS6 y se ve bien en iOS7 también
PERO cuando ejecuto la aplicación en iOS7, este es el tipo de mensaje que veo en la consola:
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-10-02 09:56:44.847 Vente-Exclusive[76306:a0b] 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:0xac4c5f0 V:|-(15)-[UIImageView:0xac47f50] (Names: ''|'':UITableViewCellContentView:0xd93e850 )>",
"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
"<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>",
"<NSLayoutConstraint:0xac43680 V:[UIView:0xac4d0f0(1)]>",
"<NSLayoutConstraint:0xac436b0 V:[UIView:0xac4d0f0]-(0)-| (Names: ''|'':UITableViewCellContentView:0xd93e850 )>",
"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>
Y de hecho hay una de las limitaciones en esa lista que no quiero:
"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
y no puedo establecer la propiedad contentView
de contentView
en NO => que arruinaría toda la celda.
44 es la altura de celda predeterminada pero definí mis alturas personalizadas en el delegado de la vista de tabla, entonces ¿por qué la celda contentView tiene esta restricción? Que podria causar esto?
En iOS6 no está sucediendo y todo se ve bien en iOS6 e iOS7.
Mi código es bastante grande, así que no lo publicaré aquí, pero siéntase libre de pedir un pastebin si lo necesita.
Para especificar cómo lo estoy haciendo, en la inicialización de la celda:
- Creo todas mis etiquetas, botones, etc.
- Establecí su propiedad tralatesAutoresizingMaskIntoConstraints en NO
- Los agrego como subvistas de
contentView
de la celda -
contentView
las restricciones encontentView
También estoy profundamente interesado en comprender por qué esto sucede solo en iOS7.
A medida que se reutilizan las celdas y la altura puede cambiar en función del contenido, creo que, en general, sería mejor establecer la prioridad de los espaciados a menos de lo requerido.
En tu caso, el UIImageView tiene un espaciado de 15 en la parte superior y la vista inferior tiene un espaciado de 0 en la parte inferior. Si establece la prioridad de esas restricciones en 999 (en lugar de 1000), la aplicación no se bloqueará, porque las restricciones no son necesarias.
Una vez que se llama al método layoutSubviews, la celda tendrá la altura correcta, y las restricciones se pueden satisfacer normalmente.
Aparentemente hay algo mal con UITableViewCell y UICollectionViewCell en iOS 7 usando iOS 8 SDK.
Puede actualizar el contenido de la celda cuando la celda se reutilice de esta manera:
Para el UITableViewController estático:
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
{
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
}
//your code goes here
return cell;
}
#endif
#endif
Dado que los controladores de vista de tabla estáticos son frágiles y pueden romperse fácilmente si implementa algunos métodos de fuente de datos o métodos deletegate, existen controles que garantizarán que este código solo se compile y ejecute en iOS 7.
Es similar para UITableViewController dinámico estándar:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"CellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
{
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
}
//your code goes here
return cell;
}
Para este caso no necesitamos la verificación adicional de compilación, ya que se requiere implementar este método.
La idea es la misma para ambos casos y para UICollectionViewCell, como se comenta en este hilo: Autoreizing issue of UICollectionViewCell El marco de ContentView en la celda prototipo Storyboard (Xcode 6, iOS 8 SDK) ocurre cuando se ejecuta en iOS 7 solamente
Si funciona bien en iOS8, y recibe la advertencia en iOS7, puede buscar el código fuente del guion gráfico, encontrar la tabla de visión correcta, y luego agregar el atributo rect después de la línea tableViewCell. Gracias a kuchumovn .
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" .../>
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
Simplemente aumente la altura de celda predeterminada. Parece que el problema es que el contenido de la celda es más grande que el tamaño predeterminado (inicial) de la celda, lo que infringe algunas restricciones no negativas hasta que la celda se redimensiona a su tamaño real.
Tal vez establezca la prioridad de la vista grande de 750 y menos de 1000 puede resolver.
"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
También me enfrenté a este problema y ninguna de las sugerencias me ayudó. En mi caso, tenía la celda de selección de tamaño, y contenía collectionView inside (cada celda de collectionView contenía la imagen de tamaño completo). Ahora, la altura del tamaño de celda era un poco más grande (60) que la colecciónView (50) y las imágenes dentro de ella (50). Debido a que la vista collectionView ha alineado la restricción bottom to superview con un valor de 10. Eso me daría una advertencia, y la única manera de solucionarlo era hacer que la altura de la celda sea la misma que su collectionView.
También tuve este problema .. Parece que el marco de contentView no se actualiza hasta que se llama a layoutSubviews
sin embargo, el marco de la celda se actualiza antes, dejando el marco de contentView configurado a {0, 0, 320, 44}
en el momento cuando las restricciones son evaluadas
Después de mirar el contentView en más detalle, parece que el aumento de tamaño de Masks ya no se establece.
Configurar el autoresizingMask antes de restringir sus vistas puede resolver este problema:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
if (self)
{
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[self loadViews];
[self constrainViews];
}
return self;
}
Terminé por no usar UITableViewCell como diseñador ... Creé su vista personalizada y la agregué a la vista de contenido de la celda mediante programación ... Con algunas categorías de ayuda, tampoco hay un código repetitivo ...
Todavía no encontré una buena solución para guiones gráficos ... También hay información aquí: github.com/Alex311/TableCellWithAutoLayout/commit/…
De lo que aconsejan allí:
self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);
He inducido mi solución:
- haga clic derecho en el guión gráfico
- Abrir como -> Código fuente
- buscar la cadena "44" allí
- va a ser como
.
<tableView hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="44" ...
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ChatMessageCell" id="bCG-aU-ivE" customClass="ChatMessageCell">
<rect key="frame" x="0.0" y="22" width="320" height="44"/>
.
- reemplace rowHeight = "44" con rowHeight = "9999" y height = "44" con height = "9999"
- haga clic derecho en el guión gráfico
- Abrir como -> Constructor de interfaz
- ejecuta tu aplicación y verifica la salida
Yo tuve el mismo problema. Mi solución basada en otros arriba:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// initialize my stuff
[self layoutSubviews]; // avoid debugger warnings regarding constraint conflicts
}
return self;
}
Mejor, Alessandro