objective c - "Todavía se requiere diseño automático después de ejecutar-layoutSubviews" con la subclase UITableViewCell
constraints swift 4 (30)
Agregue sus subvistas a contentView de la celda en lugar de la celda misma. Entonces, en lugar de:
[self addSubview:someView];
debes usar
[self.contentView addSubview:someView];
Usando XCode 4.5 e iOS 6, estoy desarrollando una aplicación con una vista de tabla simple con celdas personalizadas. Lo he hecho cientos de veces en iOS 5 y versiones anteriores, pero por alguna razón el nuevo sistema de autoLayout me está causando muchos problemas.
Configuré mi vista de tabla y prototipo de celda en IB, agregué subvistas y las conecté como IBOutlets luego configuré mi delegado y dataSource. Sin embargo, ahora cada vez que se obtiene la primera celda de cellForRowAtIndexPath
, cellForRowAtIndexPath
el siguiente error:
*** Error de aserción en - [Disposición de ShopCellSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2372/UIView.m:5776
*** Aplicación de finalización debido a la excepción no detectada ''NSInternalInconsistencyException'', motivo: ''Todavía se requiere diseño automático después de ejecutar -layoutSubviews. La implementación de ShopCell de -layoutSubviews necesita llamar a super. ''
No he implementado un método -layoutSubviews en mi celda subclasificada (ShopCell), e incluso cuando trato de hacerlo y agrego la súper llamada, ya que sugiere, sigo recibiendo el mismo error. Si elimino las subvistas de la celda en IB y las cambio a una UITableViewCell estándar, todo funciona como se espera, aunque, por supuesto, no tengo datos en mis celdas.
Estoy casi seguro de que me falta algo simple, pero no puedo encontrar ninguna documentación o guía que sugiera lo que hice mal. Cualquier ayuda sería apreciada.
Editar: intenté cambiarlo a UITableViewCell en IB y dejando todas las subvistas en su lugar, sigue siendo el mismo error.
Aparentemente, la implementación layoutSubviews de UITableViewCell no llama a super, que es un problema con el diseño automático. Me interesaría ver si eliminar la categoría inferior en proyectos soluciona las cosas. Ayudó en un proyecto de prueba.
#import <objc/runtime.h>
#import <objc/message.h>
@implementation UITableViewCell (FixUITableViewCellAutolayoutIHope)
+ (void)load
{
Method existing = class_getInstanceMethod(self, @selector(layoutSubviews));
Method new = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews));
method_exchangeImplementations(existing, new);
}
- (void)_autolayout_replacementLayoutSubviews
{
[super layoutSubviews];
[self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
[super layoutSubviews];
}
@end
Podría agregar el problema que se me presentó al usar una vista de fondo en la celda de la tabla, ya que se agrega como una subvista a la celda (mientras que la mayoría de las subvistas deben agregarse al contenido de la celda de la tabla, que normalmente debería funcionar mejor).
Nota: Parece que este error está solucionado en iOS7; Pude eliminar este código, o al menos agregar una verificación en tiempo de ejecución para que solo se ejecute si se ejecuta en iOS6.
Como ya se ha mencionado anteriormente, cuando crea una vista para usar en una UITableView, debe eliminar la vista creada de manera predeterminada y arrastrar una UITableViewCell o UITableViewHeaderFooterView como vista raíz. Sin embargo, hay una manera de arreglar el XIB en caso de que se haya perdido esa parte. Tienes que abrir el archivo XIB en un editor de texto y en la etiqueta raíz y su hijo directo agrega / cambia el atributo translatesAutoresizingMaskIntoConstraints
a YES
, por ejemplo
<view contentMode="scaleToFill" horizontalHuggingPriority="1000" id="1" translatesAutoresizingMaskIntoConstraints="YES" customClass="MXWCollapsibleTableHeaderView">
El problema es la secuencia de las llamadas de diseño a las subvistas:
Revisa
Se muestra en iOS <8
En algunas situaciones, esto resuelve el problema de diseño fácilmente (dependiendo de su diseño). Dentro de la subestación UITableView, en awakeFromNib o init, configure la máscara de aumento automático:
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Por defecto, está configurado en UIViewAutoresizingNone
En mi caso,
El UIImageView referenciado para el diseño automático de UITableView se asigna a backgroundView de UITableView.
self.tableView.backgroundView = self.tableBackgroundImageView;
Entonces, eliminé UIImageView para backgroundView de UIView (Root view) y restablecí (eliminé) toda la referencia de diseño automático a ese UIImageView. Puse ese UIImageView para el fondo en el exterior de la UIView (vista raíz). Y luego asigne a la vista de fondo de UITableView en el código.
Luego arreglado.
Encontré el mismo problema y finalmente encontré que la razón era que agregué una restricción al UITableViewCell, que debería ser el contentView de UITableViewCell . Cuando cambié la restricción, ¡todo salió bien!
Encontré este porque inicialmente había agregado un UIView en lugar de un UITableViewCell a un archivo xib.
Estaba viendo esto como resultado de la modificación de restricciones en mi implementación de layoutSubviews. Mover la llamada a super desde el principio hasta el final del método solucionó el problema.
Este problema puede deberse a que olvidó llamar a [super viewDidAppear:]
dentro de viewDidAppear
, pero estoy seguro de que no es la única causa.
Fui tuve el mismo problema. Fui a mi DetailViewController y cambié el nombre del identificador a UIView. Anteriormente estaba en UITableView. Solucionó el problema. Este problema no tiene que ser en su DetailViewController. Podría ser en cualquier otro. Intente cambiarle el nombre al identificador respetado.
He encontrado la solución.
En mi caso, creé la vista de celda en el guión gráfico (con el diseño automático habilitado) y definí la interfaz UITableViewCell personalizada en mi ViewController.m, tengo que mover la interfaz a ViewController.h.
He estado experimentando lo mismo. Resultó que si programáticamente agrega una subvista desde su ShopCell .xib / storyboard, que utiliza el diseño automático, como una subvista a otra vista, esa excepción podría ser lanzada, dependiendo de cómo se configuran sus restricciones. Mi suposición es que las restricciones creadas en IB es lo que crea los problemas cuando se agrega una vista como una subvista mediante programación, ya que entonces mantiene restricciones de viewA -> viewB mientras tanto, puede agregar viewB como una subvista de viewC. Lo tienes (esa frase incluso me confunde)?
En mi situación, ya que las vistas muy simples fueron las que causaron el problema, creé las vistas de forma programática y no en IB. Eso lo resolvió Puede extraer esas vistas a otros archivos xib y deshabilitar el diseño automático para esos. Supongo que eso funcionaría.
Me encontré con el mismo problema al agregar restricciones manualmente en el código. En código, yo estaba haciendo lo siguiente:
{
[self setTranslatesAutoresizingMaskIntoConstraints:YES];
[self addSubview:someView];
[self addSubview:someOtherView];
[self addConstraint:...];
}
Hipótesis
Por lo que puedo decir, el problema es que cuando inhabilitas traduceAutoresizingMaskIntoConstraints, UITableViewCell comienza a utilizar Diseño automático y, naturalmente, falla porque la implementación subyacente de layoutSublayersForLayer
no llama súper. Alguien con Hopper o alguna otra herramienta puede confirmar esto. Dado que está utilizando IB, probablemente se esté preguntando por qué esto es un problema ... y eso se debe a que el uso de IB inhabilita automáticamente traduceAutlasizingMaskIntoConstraints para las vistas a las que agrega restricciones (automáticamente agregará una restricción de ancho y alto en su lugar).
Solución
Mi solución fue mover todo a contentView
.
{
[self.contentView addSubview:someView];
[self.contentView addSubview:someOtherView];
[self.contentView addConstraint:...];
}
No estoy 100% seguro de si esto funcionará en Interface Builder, pero si sacas todo de tu celular (suponiendo que tienes algo directamente en él), entonces debería funcionar. ¡Espero que esto te ayude!
Me encontré con el mismo problema cuando uso el guión gráfico para crear el UITableViewCell personalizado. Afortunadamente, encontré el problema, porque desconecté el accessView ([UITableViewCell setAccessoryView:]) a UIButton que agregué a la celda.
Así que ocurrió en mi proyecto cuando se ejecuta en el iOS6.
Solución
Suelte la salida entre accessoryView y mi botón que contenía la celda personalizada.
Propuesta
No debe usar los elementos nativos de UITableViewCell y cambiarlos.
Me encontré con este problema por primera vez hoy. Hasta ahora tenía varias experiencias en el uso de subclases prototipo de UITableViewCell, pero nunca me encontré con este problema. Lo que era diferente acerca de la celda con la que estaba trabajando era que tenía un IBOutlet en la vista de fondo que estaba usando para colorear la celda. Descubrí que si creé una nueva propiedad y aún agregué una nueva UIView que extendía el lapso de toda la celda, esta afirmación desapareció. Para verificar que esta era la causa, volví a adjuntar esta vista a la salida de backgroundView y la aserción reapareció. Hasta el momento, no hay otros problemas al utilizar AutoLayout en un prototipo subcompuesto UITableViewCell desde que hice este cambio.
Me encuentro con esto y parece que está relacionado con las subclases UITableViewCell como células prototipo que tienen específicamente otras subclases UIView personalizadas. Enfatizo la ''costumbre'' aquí porque he tenido éxito con células que solo tienen hijos UIKit, pero se cae al tratar de construir las restricciones para las vistas que he creado a medida, arrojando el error indicado en la pregunta de los autores.
He tenido que separar mis celdas en puntas independientes que no usan AutoLayout.
Esperemos que Apple limpie este desastre.
No obtuve ninguna solución adecuada para este problema, pero puede solucionarlo utilizando marcos y no estableciendo la propiedad traducirAutlasizingMaskIntoConstraints a No (de manera predeterminada, sí, así que no lo configure)
CGRect headerViewFrame = CGRectMake(0,0,320,60); //Frame for your header/footer view
UIView *tableHeaderView = [[UIView alloc] initWithFrame:headerViewFrame];
tableHeaderView.translatesAutoresizingMaskIntoConstraints = Yes; //Or don''t set it at all
[self.tableView setTableHeaderView:tableHeaderView];
Resolví el problema al desactivar "Autolayout" para todas las subvistas de mi celda de vista de tabla personalizada.
En el xib para una celda personalizada, seleccione una subvista y desmarque File Inspector> Interface Builder Document> Use Autolayout
Solución: cambiar las restricciones antes de llamar a superdisposiciónSubviews
- (void)layoutSubviews
{
[self _updateConstraints];
[super layoutSubviews];
}
Tenía exactamente el mismo problema. Aquí está el problema con mi proyecto:
Cuando trabajé en Interface Builder para crear una UITableViewCell personalizada, arrastré una vista en lugar de una celda de vista de tabla desde el panel de colección de objetos en Xcode
como la celda de la tabla personalizada.
Si se encuentra en la misma situación, aquí está la solución:
Elimine la vista en el constructor de interfaz, asegúrese de arrastrar una celda de vista de tabla desde el panel de colección de objetos y vuelva a hacer la vista de celda de la tabla personalizada. Puede copiar los objetos en la vista anterior y pegarlos en el lienzo de la nueva celda de vista de tabla.
Tuve el mismo error durante algunos meses. Pero encontré cuál era el problema.
Cuando creo un archivo IB, ya se agrega una UIView
. Si usa esta vista, la aplicación no se bloquea cuando el diseño automático está desactivado (pero hay otros problemas). Cuando usa el diseño automático, debe seleccionar la vista correcta en la Biblioteca de objetos: UITableViewCell
.
De hecho, siempre debe usar este elemento porque todas las subvistas se agregan al contentView
de UITableViewCell
.
Eso es todo. Todo estará bien.
Tuve el mismo problema con el UITableViewHeaderFooterView
+ xib personalizado.
Vi algunas respuestas aquí, pero encontré la implementación -layoutSubviews
en mi clase de vista de pie de página personalizada corrige el problema:
-(void)layoutSubviews
{
[super layoutSubviews];
[self layoutIfNeeded]; // this line is key
}
Tuve el mismo problema en iOS 7 (iOS 8 parece arreglar). La solución para mí fue llamar a [self.view layoutIfNeeded]
al final de mi método viewDidLayoutSubviews
.
Tuve el mismo problema. El problema estaba en la forma en que estaba creando la celda Xib. Creé un Xib como normal y simplemente cambié el tipo de "UIView" por defecto a mi clase UITableViewCell personalizada. La forma correcta de hacerlo es primero eliminar la vista predeterminada y luego arrastrar el objeto de celda de vista de tabla al xib. Más detalles aquí: http://allplayers.github.io/blog/2012/11/18/Custom-UITableViewCell-With-NIB/
Tuve un problema muy similar con una vista de pie de tabla que estaba configurando en Xcode 6, iOS 7+. La solución estaba en el formato del archivo de punta. Aparentemente estaba atascado en formato Xcode 4 o algo así. Cambiando la configuración del archivo a "opens in: Xcode 6.0" (o Default, para el caso), lo arregló instantáneamente. Encontré la solución por casualidad: me estaba volviendo loco, así que borré todo el archivo y lo volví a crear, obviamente con la configuración predeterminada. No tengo idea de por qué simplemente editar el archivo en el último Xcode no lo convirtió a un formato Xcode 5+, como suele suceder.
Tuve un problema similar con las celdas de vista de tabla estática en IB. Una de las celdas tenía una subvista que tenía una clase que se había alterado por error a una subclase de UITextfield. El compilador no dio ninguna advertencia / error. Pero en el tiempo de ejecución, el sistema no pudo cargar el controlador de vista con el bloqueo antes mencionado como resultado.
Tuve un problema similar no en UITableViewCell
sino en UITableView
. Debido a que es el primer resultado en Google, lo publicaré aquí. Resultó que viewForHeaderInSection
era el problema. UITableViewHeaderFooterView
un UITableViewHeaderFooterView
y establecí UITableViewHeaderFooterView
en NO
. Ahora aquí viene la parte interesante:
ios 7:
// don''t do this on iOS 7
sectionHeader.translatesAutoresizingMaskIntoConstraints = NO;
Si hago esto la aplicación se bloquea con
El diseño automático aún se requiere después de ejecutar -layoutSubviews. Implementación de UITableView de -layoutSubviews necesita llamar súper.
De acuerdo, pensé que no puedes usar el diseño automático en un encabezado de vista de tabla y solo en las subvistas. Pero esa no es toda la verdad como lo ves más tarde. En resumen: no desactive la máscara de cambio de tamaño automático para el encabezado en iOS 7. De lo contrario, está funcionando bien.
iOS 8:
// you have to do this, otherwise you get an auto layout error
sectionHeader.translatesAutoresizingMaskIntoConstraints = NO;
Si no lo usara, obtendría el siguiente resultado:
Incapaz de satisfacer restricciones simultáneamente.
Para iOS 8, debe desactivar la máscara de cambio de tamaño automático para el encabezado.
No sé por qué se comporta de esta manera, pero parece que Apple arregló algunas cosas en iOS 8 y el diseño automático funciona de manera diferente en iOS 7 e iOS 8.
UIImageView
este error desacoplando el conector backgroundView
de mi UIImageView
fondo y el conector accessoryView
desde mis personalizaciones de UIButton
. Sospecho que estos no fueron diseñados para usarse de la manera en que los estaba usando.
UITableView
la respuesta de Carl Lindberg para anular UITableView
y comenzó a funcionar para mí:
UITableView + AutoLayoutFix.h
@interface UITableView (AutoLayoutFix)
@end
UITableView + AutoLayoutFix.m
#import <objc/runtime.h>
@implementation UITableView (AutoLayoutFix)
+ (void)load
{
Method existingMethod = class_getInstanceMethod(self, @selector(layoutSubviews));
Method newMethod = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews));
method_exchangeImplementations(existingMethod, newMethod);
}
- (void)_autolayout_replacementLayoutSubviews
{
[super layoutSubviews];
[self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
[super layoutSubviews];
}
@end
Luego en MyViewController.m
Acabo de importar la categoría:
#import "UITableView+AutoLayoutFix.h"