Crear restricciones de diseño mediante progtwigción

Sé que muchas personas ya hicieron muchas preguntas al respecto, pero incluso con las respuestas no puedo hacer que funcione.

Cuando estoy lidiando con restricciones en el guión gráfico, es fácil, pero en el código tengo dificultades. Intento, por ejemplo, tener una vista que permanezca en el lado derecho y que tenga la altura de la pantalla según la orientación de la pantalla. Este es mi código:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)]; myView.backgroundColor = [UIColor redColor]; [self.view addSubview:myView]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; 

No satisface algunas restricciones. No veo lo que está mal. Además, ¿por qué no puedo usar una propiedad como self.myView lugar de una variable local como myView ?

Cuando se utiliza el diseño automático en el código, establecer el marco no hace nada. Por lo tanto, el hecho de que haya especificado un ancho de 200 en la vista anterior no significa nada cuando establece restricciones en él. Para que la restricción de una vista sea inequívoca, necesita cuatro cosas: una posición x, una posición y, un ancho y una altura para cualquier estado dado.

Actualmente, en el código anterior, solo tiene dos (altura, relativa a la supervista y posición y, relativa a la supervista). Además de esto, tiene dos restricciones obligatorias que podrían entrar en conflicto dependiendo de cómo se configuran las restricciones de la vista de la vista. Si la supervista tuviera una restricción requerida que especifique que su altura es un valor inferior a 748, obtendrá una excepción de “restricciones insatisfactorias”.

El hecho de que haya establecido el ancho de la vista antes de establecer restricciones no significa nada. Ni siquiera tomará en cuenta el marco anterior y calculará un nuevo marco basado en todas las restricciones que ha especificado para esas vistas. Cuando se trata de autolayout en código, normalmente solo creo una nueva vista usando initWithFrame:CGRectZero o simplemente init .

Para crear el conjunto de restricciones requerido para el diseño que describió verbalmente en su pregunta, deberá agregar algunas restricciones horizontales para vincular el ancho y la posición x para dar un diseño completamente especificado:

 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[myView(==200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; 

Verbalmente describiendo este diseño se lee de la siguiente manera comenzando con la restricción vertical:

myView llenará la altura de su supervista con un relleno superior e inferior igual al espacio estándar. La supervista de myView tiene una altura mínima de 748pts. El ancho de myView es de 200 pts y tiene un margen derecho igual al espacio estándar en comparación con su supervista.

Si simplemente desea que la vista ocupe toda la altura de la supervista sin restringir la altura de la supervista, omita el parámetro (>=748) en el texto del formato visual. Si cree que el parámetro (>=748) es necesario para darle una altura, no lo hace en esta instancia: fijar la vista a los bordes de la supervista utilizando la barra ( | ) o la barra con espacio ( |- , -| ) syntax, le está dando a su vista una posición y (fijando la vista en un solo borde), y una posición y con alto (fijando la vista en ambos bordes), satisfaciendo así su conjunto de restricciones para la vista.

En lo que respecta a su segunda pregunta:

Utilizando NSDictionaryOfVariableBindings(self.myView) (si tiene una configuración de propiedad para myView) y alimentarlo en su VFL para usar self.myView en su texto VFL, probablemente obtendrá una excepción cuando autolayout intente analizar su texto VFL. Tiene que ver con la notación de punto en las teclas del diccionario y el sistema que intenta usar valueForKeyPath: Vea aquí para una pregunta y respuesta similar .

Hola, he estado usando mucho esta página para las restricciones y “cómo hacerlo”. Me llevó una eternidad llegar al punto de darme cuenta de que necesitaba:

 myView.translatesAutoresizingMaskIntoConstraints = NO; 

para que este ejemplo funcione Gracias Userxxx, Rob M. y especialmente larsacus por la explicación y el código aquí, ha sido invaluable.

Aquí está el código completo para que se ejecuten los ejemplos anteriores:

 UIView *myView = [[UIView alloc] init]; myView.backgroundColor = [UIColor redColor]; myView.translatesAutoresizingMaskIntoConstraints = NO; //This part hung me up [self.view addSubview:myView]; //needed to make smaller for iPhone 4 dev here, so >=200 instead of 748 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[myView(==200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; 

Versión Swift

Actualizado para Swift 3

Este ejemplo mostrará dos métodos para agregar las siguientes restricciones programáticamente de la misma manera que si lo hiciera en Interface Builder:

Anchura y altura

enter image description here

Centro en contenedor

enter image description here

Código repetitivo

 override func viewDidLoad() { super.viewDidLoad() // set up the view let myView = UIView() myView.backgroundColor = UIColor.blue myView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(myView) // Add constraints code here (choose one of the methods below) // ... } 

Método 1: Estilo de anclaje

 // width and height myView.widthAnchor.constraint(equalToConstant: 200).isActive = true myView.heightAnchor.constraint(equalToConstant: 100).isActive = true // center in container myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 

Método 2: NSLayoutConstraint Style

 // width and height NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true // center in container NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true 

Notas

  • El estilo de anclaje es el método preferido sobre NSLayoutConstraint Style, sin embargo, solo está disponible en iOS 9, por lo que si admite iOS 8, debe seguir utilizando NSLayoutConstraint Style.
  • Consulte también la documentación Creación programática de restricciones .
  • Vea esta respuesta para un ejemplo similar de agregar una restricción de fijación.

En cuanto a su segunda pregunta acerca de las propiedades, puede usar self.myView solo si la declaró como una propiedad en la clase. Como myView es una variable local, no puede usarlo de esa manera. Para obtener más detalles sobre esto, le recomendaría que revise la documentación de Apple en Declared Properties ,

¿Por qué no puedo usar una propiedad como self.myView lugar de una variable local como myView?

Intenta usar:

 NSDictionaryOfVariableBindings(_view) 

en lugar de self.view

Tenga en cuenta también que desde iOS9 podemos definir restricciones programáticamente “más concisas y fáciles de leer” utilizando subclases de la nueva clase auxiliar NSLayoutAnchor .

Un ejemplo del doc:

 [self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;