Hola Habr! Le presento la traducción del artículo
Creación de restricciones de UIViews mediante
programación mediante PureLayout por Aly Yaka.

Hoy lo guiaré a través de la creación de una interfaz de usuario de aplicación móvil simple con código, sin usar guiones gráficos o NIB. No entraré en discusiones sobre cuál es mejor, porque todo tiene sus pros y sus contras, por lo que simplemente
dejaré un enlace que entra en este asunto .
En la segunda parte de esta guía, crearemos algunos de los elementos de interfaz de usuario de aplicaciones móviles más comúnmente utilizados con código, incluida una barra de navegación, vista de tabla y celdas de tamaño dinámico.
Revisar
Este tutorial fue escrito usando Xcode 9 y Swift 4. También supongo que está familiarizado con Xcode, Swift y CocoaPods.
Sin más demora, comencemos a crear nuestro proyecto: una simple aplicación de tarjeta de contacto. El propósito de este artículo es enseñarle cómo crear la interfaz de usuario de su aplicación en código y, por lo tanto, no contendrá ninguna lógica con respecto a la funcionalidad de la aplicación, a menos que sea necesario para los fines de esta guía.
Crear restricciones mediante programación con PureLayout
Configuración del proyecto
Comience por iniciar Xcode -> "Crear un nuevo proyecto Xcode". Seleccione "Aplicación de vista única" y haga clic en "Siguiente".

Nombra el proyecto como quieras, decidí llamarlo ContactCard. Borre las tres opciones a continuación y seleccione Swift como su lenguaje de programación, luego haga clic en Siguiente.

Seleccione una ubicación en su computadora para guardar el proyecto. Desmarca "Crear repositorio Git en mi Mac".
Dado que no utilizaremos Storyboards o NIB en este proyecto, elimine el "Main.storyboard", que se puede encontrar en Project Navigator:

Después de eso, haga clic en el proyecto en el navegador de proyectos y en la pestaña "General", busque la sección con información de implementación y elimine todo lo que está escrito en la "Interfaz principal". Esto es lo que le dice a Xcode qué archivo de Storyboard cargar cuando se inicia la aplicación, pero como acabamos de eliminar "Main.storyboard", Xcode no encontrará este archivo, lo que hará que la aplicación se bloquee.

Crear un ViewController
Si ejecuta la aplicación ahora, aparecerá una pantalla en negro, ya que la aplicación ahora no tiene fuente de la interfaz de usuario, por lo que en la siguiente parte la crearemos. Abra "AppDelegate.swift" y dentro de la
application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?)
, Pegue este fragmento de código:
self.window = UIWindow(frame: UIScreen.main.bounds) let viewController = ViewController() self.window?.rootViewController = viewController self.window?.makeKeyAndVisible()
Este código proporciona una ventana para la interacción del usuario con la aplicación, que generalmente se puede encontrar en "ViewController.swift". Para verificar rápidamente que todo funciona, vaya a "ViewController.swift" y en el método
viewDidLoad()
, inserte la siguiente línea:
self.view.backgroundColor = .blue
Ahora ejecuta la aplicación.
Para navegar entre archivos en Xcode, use las teclas de acceso rápido "⇧⌘O", y luego ingrese el nombre del archivo o incluso el fragmento de código que está buscando, y aparecerá una lista de archivos entre los que puede elegir en la pantalla.
Después de iniciar la aplicación, este debería ser el resultado en la pantalla de su simulador:

Por supuesto, no usaremos este desagradable azul, así que simplemente cambie el fondo a blanco reemplazando
.blue
con
.white
inside
viewDidLoad ()
.
Desarrollo de interfaz de usuario
Para crear nuestra interfaz de usuario, utilizaremos una
biblioteca que nos facilitará la vida. Para instalar PureLayout, primero debe abrir su terminal y escribir cd, luego un espacio, arrastre su carpeta de proyecto al terminal y presione "Enter". Ahora ejecute los siguientes comandos dentro de la terminal:
- pod init
- instalación de pod
Esta debería ser la salida de su terminal después del segundo comando:

Después de eso, cierre Xcode, abra la carpeta en Finder y debería encontrar "<su nombre de proyecto> .xcworkspace". Esto es lo que abriremos para acceder a nuestra aplicación si alguna vez necesitamos usar CocoaPods. ¡Ahora encuentre el archivo llamado "PodFile" y escriba la siguiente línea debajo de la frase
use_frameworks!
pod “PureLayout”
Ejecute
pod install
nuevamente en su terminal, y luego construya su proyecto presionando "Command + B".
Coffee break
Ahora que todo está configurado, comencemos con el trabajo real. Vaya a "ViewController.swift" y tome una taza de café, porque así es como se verá el resultado final:

Crear ImageView
Inserte la línea de
import PureLayout
debajo de
import UIKit
para que pueda usar la biblioteca en este archivo. Luego, bajo la declaración de la clase y fuera de cualquier función, comenzamos creando la variable de perezoso (perezoso)
Avatar ImageView
siguiente manera:
lazy var avatar: UIImageView = { let imageView = UIImageView(image: UIImage(named: "avatar.jpg")) imageView.autoSetDimensions(to: CGSize(width: 128.0, height: 128.0)) imageView.layer.borderWidth = 3.0 imageView.layer.borderColor = UIColor.lightGray.cgColor imageView.layer.cornerRadius = 64.0 imageView.clipsToBounds = true return imageView }()
En cuanto a la imagen, guarde cualquier imagen en el escritorio que usará como avatar y arrástrela a Xcode en la carpeta <Your Project Name>, que en mi caso se llama "ContactCard", y marque la casilla "Copiar elementos si es necesario" .

Después de eso, escriba el nombre de este archivo junto con su extensión en la declaración UIImage en lugar de "avatar.jpg".
Para aquellos de ustedes que no saben, las variables diferidas son similares a las variables ordinarias, excepto que no se inicializan (o se asigna algo de espacio de memoria) hasta que se necesiten o se llamen por primera vez. . Esto significa que las variables perezosas no se inicializan cuando se inicializa el controlador de vista, sino que esperan un punto posterior cuando realmente se necesitan, lo que ahorra potencia de procesamiento y espacio de memoria para otros procesos. Esto es especialmente útil cuando se inicializan componentes de la interfaz de usuario.
PureLayout en acción
Como puede ver dentro de la inicialización, la línea
imageView.autoSetDimensions (to: CGSize (width: 128.0, height: 128.0))
es PureLayout en acción. En una línea, establecemos un límite para la altura y el ancho del UIImageView, y se crean todas las NSLayoutConstraints necesarias sin la necesidad de grandes llamadas a funciones. Si estaba tratando de crear restricciones mediante programación, lo más probable es que ya se haya enamorado de esta maravillosa biblioteca.
Para hacer esta imagen redonda, establecemos su radio angular a la mitad de su ancho o alto, que es 64.0 puntos. Además, establezca la propiedad
clipsToBounds
en
true
, que le dice a la imagen que debe recortar todo lo que está fuera del radio que acabamos de establecer.
Luego pasamos a crear una UIView que servirá como la parte superior de la vista detrás del avatar pintado de gris. Declare la siguiente variable perezosa para esta vista:
lazy var upperView: UIView = { let view = UIView() view.autoSetDimension(.height, toSize: 128) view.backgroundColor = .gray return view }()
Agregar subvistas
Antes de continuar, creemos una
func addSubviews ()
que agregue las vistas que acabamos de crear (y todas las demás que vamos a crear) como subvistas al controlador de vista:
func addSubviews() { self.view.addSubview(avatar) self.view.addSubview(upperView) }
Ahora agregue la siguiente línea para
viewDidLoad (): self.addSubviews ()
Establecer restricciones
Para tener una idea de cuán lejos hemos llegado, establezcamos límites en estos dos tipos. Cree otra función llamada
func setupConstraints()
e inserte las siguientes restricciones:
func setupConstraints() { avatar.autoAlignAxis(toSuperviewAxis: .vertical) avatar.autoPinEdge(toSuperviewEdge: .top, withInset: 64.0) upperView.autoPinEdge(toSuperviewEdge: .left) upperView.autoPinEdge(toSuperviewEdge: .right) upperView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .bottom) }
Ahora dentro de
viewDidLoad()
llame a
setupConstraints()
, de la siguiente manera:
self.setupConstraints()
. Agregue esto DESPUÉS de llamar a
addSubviews()
. Esta debería ser la conclusión final:

Trae avatar a la vanguardia
Lamentablemente, esto no es lo que me gustaría recibir. Como puede ver, nuestro
upperView
encuentra en la parte superior del avatar. Esto se debe al hecho de que agregamos un avatar como
subviews
antes de
upperView
, y dado que estas subvistas se encuentran de alguna forma en la pila, obtenemos este resultado. Para solucionar esto, simplemente podemos reemplazar estas dos líneas entre sí, pero hay otro truco que quiero mostrarle, a saber:
self.view.bringSubview (toFront: avatar)
.
Este método transferirá el avatar de la parte inferior de la pila a la parte superior, así que elige el método que más te guste. Por supuesto, para facilitar la lectura, es mejor agregar subvistas en el orden en que deben mostrarse si se cruzan, mientras recuerda que las primeras subvistas agregadas estarán en la parte inferior de la pila y, por lo tanto, cualquier otra vista de intersección aparecerá en la parte superior.
Y así es como debería verse:

Crear control segmentado
A continuación, crearemos un control segmentado, que es una barra gris que contiene tres secciones. En realidad, un control segmentado es fácil de crear. Haz lo siguiente:
lazy var segmentedControl: UISegmentedControl = { let control = UISegmentedControl(items: ["Personal", "Social", "Resumè"]) control.autoSetDimension(.height, toSize: 32.0) control.selectedSegmentIndex = 0 control.layer.borderColor = UIColor.gray.cgColor control.tintColor = .gray return control }()
Creo que todo está claro, la única diferencia es que después de la inicialización, le proporcionamos una serie de cadenas, cada fila es el encabezado de una de nuestras secciones deseadas. También establecemos
selectedSegmentIndex
en 0, que le dice al control segmentado que seleccione / seleccione el primer segmento durante la inicialización. El resto es solo un estilo para jugar.
Ahora vamos a agregarlo como una subvista insertando la siguiente línea al final de la función
addCubviews(): self.view.addSubview(segmentedControl)
y sus limitaciones serán las siguientes:
segmentedControl.autoPinEdge(toSuperviewEdge: .left, withInset: 8.0) segmentedControl.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0) segmentedControl.autoPinEdge(.top, to: .bottom, of: avatar, withOffset: 16.0)
Le decimos al control segmentado que queremos adjuntarlo al lado izquierdo de su supervista, sin embargo, queremos aumentar ligeramente el intervalo y no adjuntarlo directamente al borde de la pantalla. Si te das cuenta, utilizo la llamada cuadrícula de ocho puntos, donde todas las distancias y tamaños son múltiplos de ocho. Hago lo mismo en el lado derecho del control segmentado. En cuanto a la última limitación, dice que adjunte la parte superior a la base del avatar con un intervalo de 16 puntos.
Después de agregar las limitaciones anteriores a
func setupConstraints()
ejecute el código y asegúrese de que se vea así:

Agregar un botón
Ahora pasaremos a la última parte de la interfaz de usuario del libro de texto, que es un botón "Editar". Agregue la siguiente variable perezosa:
lazy var editButton: UIButton = { let button = UIButton() button.setTitle("Edit", for: .normal) button.setTitleColor(.gray, for: .normal) button.layer.cornerRadius = 4.0 button.layer.borderColor = UIColor.gray.cgColor button.layer.borderWidth = 1.0 button.tintColor = .gray button.backgroundColor = .clear button.autoSetDimension(.width, toSize: 96.0) button.autoSetDimension(.height, toSize: 32.0) return button }()
No se preocupe por lo grande que es la inicialización, pero preste atención a cómo configuro el título y su color llamando a las
button.setTitleColor
button.setTitle
y
button.setTitleColor
. Por ciertas razones, no podemos establecer el título de un botón accediendo directamente a su
titleLabel
, y esto se debe a que hay diferentes estados para el botón, y muchos se sentirían cómodos teniendo diferentes encabezados / colores para diferentes estados.
Ahora agregue el botón como una subvista, como el resto de los componentes, y agregue las siguientes restricciones para que aparezca donde debería estar:
editButton.autoPinEdge(.top, to: .bottom, of: upperView, withOffset: 16.0) editButton.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0)
Aquí establecemos solo los límites derecho y superior para el botón, porque le dimos un tamaño, no se expandirá y no se necesitará nada más. Ahora ejecute el proyecto para ver el resultado final:

Algunas notas recientes
Practique, agregue tantos elementos de interfaz como desee. Cree vistas de cualquier aplicación que le resulte difícil. Comience de manera simple y aumente gradualmente la dificultad. Intente dibujar componentes de la interfaz de usuario en una hoja de papel para imaginar cómo encajan entre sí.
En la segunda parte, extiendo esta guía para crear una barra de navegación, vista de tabla y celdas de tamaño dinámico en el código.