Tengo un sistema UITableView
operativo con iOS 8 y estoy usando alturas de celda automáticas a partir de restricciones en un guión gráfico.
Una de mis celdas contiene una sola UITextView
y la necesito para contraer y expandir según la entrada del usuario: toque para reducir / expandir el texto.
Estoy haciendo esto agregando una restricción de tiempo de ejecución a la vista de texto y cambiando la constante en la restricción en respuesta a los eventos del usuario:
-(void)collapse:(BOOL)collapse; {
_collapsed = collapse;
if(collapse)
[_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
else
[_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];
[self setNeedsUpdateConstraints];
}
Cuando hago esto, lo envuelvo en tableView
actualizaciones y llamo [tableView setNeedsUpdateConstraints]
:
[tableView beginUpdates];
[_briefCell collapse:!_showFullBriefText];
[tableView setNeedsUpdateConstraints];
// I have also tried
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.
[tableView endUpdates];
Cuando hago esto, mi celda se expande (y se anima mientras lo hace) pero recibo una advertencia de restricciones:
2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] 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:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",
"<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-| (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'] (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>
388 es mi altura calculada, las otras restricciones UITextView
son mías de Xcode / IB.
El último me está molestando, supongo que esa UIView-Encapsulated-Layout-Height
es la altura calculada de la celda cuando se renderiza por primera vez (configuro mi UITextView
altura como> = 70.0), sin embargo, no parece correcto que esta restricción derivada anule un Cnstraint de usuario actualizado.
Peor aún, aunque el código de diseño dice que está tratando de romper mi restricción de altura, no lo hace; continúa recalculando la altura de la celda y todo se dibuja como quisiera.
Entonces, ¿qué es NSLayoutConstraint
UIView-Encapsulated-Layout-Height
(supongo que es la altura calculada para el tamaño de celda automático) y cómo debo forzarlo a que vuelva a calcular limpiamente?
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
. Creo que establecer inicialmente la máscara de tamaño automático evita que se agregue la última restricción. Encontré esta solución aquí: github.com/wordpress-mobile/WordPress-iOS/commit/…<rect key="frame" x="0.0" y="0.0" width="600" height="110"/>
en su definición, lo que me hizo creer que se trataba de un error de IB . Al menos el mío era de todos modos.Respuestas:
Intente reducir la prioridad de su
_collapsedtextHeightConstraint
a 999. De esa manera, laUIView-Encapsulated-Layout-Height
restricción proporcionada por el sistema siempre tiene prioridad.Se basa en lo que regresas
-tableView:heightForRowAtIndexPath:
. Asegúrese de devolver el valor correcto y su propia restricción, y la generada debe ser la misma. La prioridad más baja para su propia restricción solo es necesaria temporalmente para evitar conflictos mientras las animaciones de colapso / expansión están en vuelo.fuente
UIView-Encapsulated-Layout-Height
restricción se añade por UITableView una vez que se determinan las alturas.systemLayoutSizeFittingSize
Calculo la altura en función de la contentView. Aquí, elUIView-Encapsulated-Layout-Height
no importa. Luego, tableView establece contentSize explícitamente en el valor devuelto porheightForRowAtIndexPath:
. En este caso, es correcto reducir la prioridad de nuestras restricciones personalizadas porque la restricción tableView debe tener prioridad después de que se calculen los altos de fila.UIView-Encapsulated-Layout-Height
está mal si no disminuyo la prioridad ...UIView-Encapsulated-Layout-Width
en mi caso es simplemente incorrecto, pero parece preferirse a mis restricciones explícitas en tiempo de ejecución.Tengo un escenario similar: una vista de tabla con una celda de fila, en la que hay algunas líneas de objetos UILabel. Estoy usando iOS 8 y autolayout.
Cuando roté, obtuve la altura de fila calculada por el sistema incorrecto (43.5 es mucho menor que la altura real). Parece que:
No es solo una advertencia. El diseño de mi celda de vista de tabla es terrible: todo el texto se superpone en una línea de texto.
Me sorprende que la siguiente línea "solucione" mi problema mágicamente (la reproducción automática no se queja y obtengo lo que espero en la pantalla):
con o sin esta línea:
fuente
estimatedRowHeight
más a menudocellForRowAtIndexPath
se llamará inicialmente. altura de la vista de tabla dividida por los tiempos estimados de RowHeight, para ser exactos. En un iPad Pro de 12 pulgadas, esto puede ser un número de miles y afectará la fuente de datos y puede provocar un retraso significativo.Pude hacer que la advertencia desapareciera especificando una prioridad en uno de los valores en la restricción que los mensajes de advertencia dicen que tenía que romperse (a continuación
"Will attempt to recover by breaking constraint"
). Parece que mientras establezca la prioridad en algo mayor que49
, la advertencia desaparece.Para mí, esto significaba cambiar mi restricción, la advertencia decía que intentaba romper:
@"V:|[contentLabel]-[quoteeLabel]|"
a:
@"V:|-0@500-[contentLabel]-[quoteeLabel]|"
De hecho, puedo agregar una prioridad a cualquiera de los elementos de esa restricción y funcionará. No parece importar cuál. Mis celdas terminan a la altura adecuada y no se muestra la advertencia. Roger, por ejemplo, intenta agregar
@500
justo después de la388
restricción del valor de altura (por ejemplo388@500
).No estoy completamente seguro de por qué esto funciona, pero he investigado un poco. En la enumeración NSLayoutPriority , parece que el
NSLayoutPriorityFittingSizeCompression
nivel de prioridad es50
. La documentación para ese nivel de prioridad dice:La documentación para el
fittingSize
mensaje referenciado dice:No he cavado más allá de eso, pero parece tener sentido que esto tenga algo que ver con el problema.
fuente
El 99.9% del tiempo, al usar celdas o encabezados personalizados, todos los conflictos
UITableViews
ocurren cuando la tabla se carga por primera vez. Una vez cargado, normalmente no volverá a ver el conflicto.Esto sucede porque la mayoría de los desarrolladores generalmente usan una altura fija o una restricción de anclaje de algún tipo para diseñar un elemento en la celda / encabezado. El conflicto ocurre porque cuando la
UITableView
primera carga / se presenta, establece la altura de sus celdas en 0. Esto obviamente entra en conflicto con sus propias restricciones. Para resolver esto, simplemente establezca cualquier restricción de altura fija a una prioridad más baja (.defaultHigh
). Lea atentamente el mensaje de la consola y vea qué restricción decidió romper el sistema de diseño. Por lo general, este es el que necesita cambiar su prioridad. Puede cambiar la prioridad de esta manera:fuente
Yo era capaz de resolver este error mediante la eliminación de una espuria
cell.layoutIfNeeded()
que tuve en mitableView
'scellForRowAt
método.fuente
En lugar de informar a la vista de tabla para actualizar sus restricciones, intente volver a cargar la celda:
UIView-Encapsulated-Layout-Height
es probablemente la altura que la vista de tabla calculó para la celda durante la carga inicial, según las restricciones de la celda en ese momento.fuente
Otra posibilidad:
Si usa el diseño automático para calcular la altura de la celda (altura de contentView, la mayoría de las veces como se muestra a continuación), y si tiene un separador de vista uitable, debe agregar la altura del separador para obtener la altura de la celda. Una vez que obtenga la altura correcta, no tendrá esa advertencia de auto-distribución.
fuente
UITableViewAutomaticDimension
enheightForRowAtIndexPath
vuelvo[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] + 0.1
[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 0.1
Como mencionó el comentario de Jesse en cuestión, esto funciona para mí:
FYI, este problema no ocurre en iOS 10.
fuente
Tuve este error al usar UITableViewAutomaticDimension y cambiar una restricción de altura en una vista dentro de la celda.
Finalmente descubrí que se debía a que el valor constante de restricción no se había redondeado al entero más cercano.
fuente
Cambiar el tamaño de la vista de texto para que se ajuste a su contenido y actualizar la constante de restricción de altura a la altura resultante, arregló el
UIView-Encapsulated-Layout-Height
conflicto de restricción para mí, por ejemplo:fuente
Después de pasar algunas horas rascándome la cabeza con este error, finalmente encontré una solución que me funcionó. mi principal problema era que tenía múltiples puntas registradas para diferentes tipos de células, pero se permitió específicamente que un tipo de célula tuviera diferentes tamaños (no todas las instancias de esa célula serán del mismo tamaño). Entonces, el problema surgió cuando la vista de tabla intentaba eliminar una celda de ese tipo y tenía una altura diferente. Lo resolví configurando
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; self.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});
cada vez que la celda tenía sus datos para calcular su tamaño. Me imagino que puede estar en
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
algo como
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; cell.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});
¡Espero que esto ayude!
fuente
TableView obtiene la altura de la celda en indexPath del delegado. luego obtener celular de
cellForRowAtIndexPath
:if cell.contentView.height: 0 // <-> (UIView-Encapsulated-Layout-Height: 0 @ 1000) top (10 @ 1000) en conflicto con (UIView-Encapsulated-Layout-Height: 0 @ 1000),
debido a que las prioridades son iguales a 1000. Necesitamos establecer la máxima prioridad bajo
UIView-Encapsulated-Layout-Height
la prioridad de.fuente
Estaba recibiendo un mensaje como este:
Estoy usando una costumbre
UITableViewCell
conUITableViewAutomaticDimension
la altura. Y también he implementado elestimatedHeightForRowAtIndex:
método.La restricción que me estaba dando problemas se parecía a esto
Cambiar la restricción a esto solucionará el problema, pero como otra respuesta, sentí que esto no era correcto, ya que reduce la prioridad de una restricción que quiero que se requiera:
Sin embargo, lo que noté es que si en realidad solo elimino la prioridad, esto también funciona y no obtengo los registros de restricción de ruptura:
Esto es un misterio en cuanto a cuál es la diferencia entre
|-6-[title]-6-|
y|-[title-|
. Pero especificar el tamaño no es un problema para mí y elimina los registros, y no necesito reducir la prioridad de mis restricciones requeridas.fuente
Establecer esto
view.translatesAutoresizingMaskIntoConstraints = NO;
debería resolver este problema.fuente
Tuve un problema similar con una celda de vista de colección.
Lo resolví bajando la prioridad de la restricción final que estaba vinculada a la parte inferior de la celda (la última en la cadena desde la parte superior a la parte inferior de la vista; esto es, en última instancia, lo que determina su altura) a 999.
La altura de la celda era correcta y las advertencias desaparecieron.
fuente