Problemas con el diseño automático en UITableViewCell


Estoy teniendo problemas con el diseño automático en un proyecto xcode 5. Estoy usando un controlador de vista simple dentro con un controlador de navegación. Tengo un MKMapView en la mitad superior y una UITableView en la mitad inferior. Estoy usando storyboards, y he configurado el prototipo UITableViewCell, pero estoy agregando las restricciones a través del código. He comprobado dos veces cada control en el prototipo y no veo ninguna restricción configurada allí. Mi problema ocurre cuando añado las restricciones para el UITableViewCell. Tengo el siguiente código en las celdas:

-(void)updateConstraints {
    [super updateConstraints];
    //first remove old constraints
    [self removeConstraints:self.constraints];
    [self.nameLabel removeConstraints:self.nameLabel.constraints];
    [self.addressLabel removeConstraints:self.nameLabel.constraints];
    [self.rentableSquareFeetLabel removeConstraints:self.rentableSquareFeetLabel.constraints];
    [self.lastSaleAmountLabel removeConstraints:self.lastSaleAmountLabel.constraints];
    [self.lastSaleDateLabel removeConstraints:self.lastSaleAmountLabel.constraints];
    [self.thumbnailImageView removeConstraints:self.thumbnailImageView.constraints];

    //then set up constraints
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_thumbnailImageView, _nameLabel, _rentableSquareFeetLabel, _lastSaleAmountLabel, _addressLabel, _lastSaleDateLabel);
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_thumbnailImageView(60)]-[_nameLabel(<=200)]-(>=8)-[_rentableSquareFeetLabel]-(>=8)-[_lastSaleAmountLabel]|" options:0 metrics:nil views:viewsDictionary]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_nameLabel]-(-4)-[_addressLabel]" options:NSLayoutFormatAlignAllLeading metrics:nil views:viewsDictionary]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_lastSaleAmountLabel]-(-4)-[_lastSaleDateLabel]" options:NSLayoutFormatAlignAllLeading metrics:nil views:viewsDictionary]];
}

Estoy recibiendo lo siguiente en la consola de depuración. La excepción se activa con la primera línea addConstraints. Si solo continúo a través de ellos, eventualmente todo se muestra como debería ser, ya que parece que xcode está eligiendo romper la restricción correcta:

2013-09-25 15:07:14.169 PECProperties[32381: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)  (
    "<NSIBPrototypingLayoutConstraint:0x9d56c70 'IB auto generated at build time for view with fixed frame' H:|-(0)-[UIImageView:0x9d558f0](LTR)   (Names: '|':UITableViewCellContentView:0x9d55620 )>",
    "<NSIBPrototypingLayoutConstraint:0x9d56d20 'IB auto generated at build time for view with fixed frame' H:[UIImageView:0x9d558f0(60)]>",
    "<NSIBPrototypingLayoutConstraint:0x9d56d80 'IB auto generated at build time for view with fixed frame' H:|-(78)-[UILabel:0x9d559e0](LTR)   (Names: '|':UITableViewCellContentView:0x9d55620 )>",
    "<NSLayoutConstraint:0x9d53830 H:[UIImageView:0x9d558f0]-(NSSpace(8))-[UILabel:0x9d559e0]>" )

Will attempt to recover by breaking constraint  <NSIBPrototypingLayoutConstraint:0x9d56d80 'IB auto generated at build time for view with fixed frame' H:|-(78)-[UILabel:0x9d559e0](LTR)   (Names: '|':UITableViewCellContentView:0x9d55620 )>

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.

El tercer NSIBPrototypingLayoutConstraint muestra 78 puntos entre el borde de la vista y una etiqueta. Ahí es donde el prototipo se coloca aproximadamente (y si lo muevo en el prototipo, veo el cambio en la restricción en la consola de depuración), pero eso entra en conflicto con mi propia restricción de distancia "estándar" entre la vista de imagen y la etiqueta.

He intentado configurar el translatesAutoresizingMaskIntoConstraints=NO en el cellForRowAtIndexPath del controlador de vista, pero eso tampoco parece ayudar. ¿Cómo puedo arreglar el diseño?

Author: Meet Doshi, 2013-09-26

1 answers

Algunas cosas para cubrir aquí:

  1. Las restricciones NSIBPrototypingLayoutConstraint con las que se está ejecutando (y que están causando excepciones) se generan automáticamente por Interface Builder para que su Storyboard o diseño de vista XIB no sea ambiguo. Es bastante astuto hacer esto, pero está agregando automáticamente las restricciones mínimas requeridas para que la posición y el tamaño de cada vista ambigua se especifiquen completamente. Este es un cambio de Xcode 4, porque en Xcode 4 no podrías tener diseños ambiguos en Interface Builder. Con Xcode 5 y posteriores puedes, sin embargo IB generará automáticamente estas restricciones si tu diseño es ambiguo en tiempo de compilación.

    La forma de solucionar este problema es agregar las restricciones mínimas requeridas en Interface Builder para que se especifique completamente la posición y el tamaño de cada vista, luego seleccione cada una de estas restricciones no deseadas, vaya a la barra lateral derecha Attributes inspector y marque la casilla junto a Placeholder-Remove at build time .

    Captura de pantalla de la casilla de verificación Marcador de posición de restricción en Xcode 6.

    Esta casilla de verificación no solo elimina la restricción que agregó, sino que lo más importante es que evitará que la restricción IB generada automáticamente tome su lugar. (Como puede imaginar, esto es bastante tedioso cuando tiene varias vistas en IB y desea administrar todas sus restricciones en el código. Por esta razón, es posible que desee evitar el uso completo de IB para jerarquías de vista en las que pretende implementar el Diseño automático mediante programación.)

    ¿Qué es el ¿diferencia entre una restricción de marcador de posición y una restricción desinstalada? Aquí hay una diapositiva de mi Charla de Diseño Automático Adaptable (video) (PDF slides ) comparando los dos:

    Comparación entre restricciones de marcador de posición y restricciones desinstaladas.

  2. En updateConstraints, no desea eliminar restricciones y volver a agregarlas como lo ha hecho allí. ¿Por qué no? Esencialmente, es terrible para el rendimiento, y he confirmado con los ingenieros de Apple que esto no es una buena idea. Ver la pregunta / respuesta que he publicado aquí para algunos detalles más, así como esta respuesta. Para evitar que las restricciones se agreguen más de una vez, use una bandera booleana (por ejemplo, hasSetupConstraints) que establezca en SÍ una vez que haya configurado sus restricciones la primera vez, y si se llama de nuevo a updateConstraints, puede regresar inmediatamente si no tiene nuevas restricciones que agregar. Ver esta pregunta para más discusión.

  3. El código que está utilizando para eliminar restricciones puede no funcionar completamente. Esto se debe a que [view removeConstraints:view.constraints] solo remove constraints that have been added to view remember recuerde que las restricciones se pueden agregar a cualquier vista superior común de las vistas que restringen!y las restricciones agregadas a view pueden no ser las únicas que afectan el diseño de view! Si necesita eliminar una serie de restricciones, debe almacenar una referencia a cada una de esas restricciones en una propiedad (por ejemplo, una propiedad NSArray que contenga instancias NSLayoutConstraint) y, a continuación, desactivar/eliminar esas restricciones mediante la API en NSLayoutConstraint o la biblioteca de código abierto PureLayout. Solo debe desactivar / eliminar el menor número posible de restricciones porque es computacionalmente costoso hacerlo. Por otro lado, cambiar el constant de cualquier restricción es muy eficiente y recomendable, y no es necesario eliminar o volver a agregar la restricción para hacerlo.

 79
Author: smileyborg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:09