Авто макет доступен уже несколько лет, но с iPhone 6 и 6 Plus он стал необходимостью для проектов. Хотя это не всегда было особенно легко в использовании, Xcode постоянно видел улучшения в Интерфейсном Разработчике, чтобы упростить интеграцию Auto Layout. В этом руководстве вы узнаете, как использовать язык визуальных форматов с помощью Swift для создания ограничений Auto Layout в коде.
1. Введение
В этом уроке предполагается, что у вас есть некоторые знания об автоматической компоновке Если вы новый Auto Layout, тогда я советую вам сначала прочитать вступление Джойса Эчессы .
Язык визуального формата — это декларативный язык, который используется для определения ограничений Auto Layout для представлений. Его синтаксис выразителен и прост для понимания, когда вы просматриваете код. Предполагаемые ограничения должны быть немедленно сняты с чтения оператора языка визуального формата, и они очень похожи на предложение.
Ограничения Auto Layout с различными приоритетами, вертикальными макетами, интервалами и размерами могут быть созданы с использованием синтаксиса Visual Format Language. Он определяется внутри строковой переменной и затем передается в методы уровня класса constraintsWithVisualFormat:options:metrics:views: and
constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: класса NSLayoutConstraint .
Язык визуального формата может быть особенно полезен, когда в Интерфейсном Разработчике нет возможности добавить ограничения Auto Layout, например, когда часть пользовательского интерфейса вашего приложения должна быть создана программно.
2. Создание нового проекта
Давайте создадим новый проект в XCode, чтобы увидеть, как используется язык визуального формата и как ваши проекты могут извлечь из этого пользу.
Шаг 1: Шаблон проекта
Откройте Xcode и выберите New> Project … из меню File . Выберите Single View Application из списка шаблонов приложений iOS и нажмите Next .

Шаг 2: Конфигурация проекта
Затем назовите ваш проект и введите название и идентификатор вашей организации. Выберите « Универсальный» в списке « Устройства» , нажмите « Далее» и выберите место для сохранения проекта. Выберите Swift в качестве языка программирования.

3. Создание ограничения для одного представления
Шаг 1: Определите переменные
Для начала создайте три переменные типа UIView . Откройте ViewController.swift и добавьте следующий код над методом viewDidLoad :
|
1
2
3
|
var vwBlue:UIView!
var vwRed:UIView!
var vwGreen:UIView!
|
Шаг 2. Инициализация представлений
Создайте функцию с именем initViews в нижней части контроллера представления void качестве его возвращаемого типа. Эта функция инициализирует представления и добавляет их в иерархию представлений. Обязательно вызовите эту функцию в viewDidLoad после вызова метода viewDidLoad суперкласса.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
func initViews() -> Void
{
//Initialize
vwRed = UIView()
vwBlue = UIView()
vwGreen = UIView()
//Prep auto layout
vwRed.setTranslatesAutoresizingMaskIntoConstraints(false)
vwBlue.setTranslatesAutoresizingMaskIntoConstraints(false)
vwGreen.setTranslatesAutoresizingMaskIntoConstraints(false)
//Coloring
vwRed.backgroundColor = UIColor.redColor()
vwBlue.backgroundColor = UIColor.blueColor()
vwGreen.backgroundColor = UIColor.greenColor()
//Add them to the view
self.view.addSubview(vwRed)
self.view.addSubview(vwBlue)
self.view.addSubview(vwGreen)
}
|
При использовании Auto Layout для представлений, созданных в коде, необходимо учитывать несколько предостережений. Первый связан со значением свойства translatesAutoresizingMaskIntoConstraints . Это свойство имеет значение true по умолчанию, что означает, что ограничения Auto Layout будут созданы на основе маски авторазмера представления . Мы хотим, чтобы представление соблюдало ограничения Auto Layout, которые мы добавим, поэтому для этого свойства должно быть установлено значение false .
Второе, что нужно иметь в виду, это жизненный цикл представления. Прежде чем ограничения Auto Layout могут быть добавлены в представление, его необходимо добавить в суперпредставление. В противном случае возникает исключение времени выполнения. Напомним, что Auto Layout определяет, где расположены представления на основе отношений. Если представление не имеет суперпредставления, операционная система не имеет контрольной точки, с которой можно связать ограничения Auto Layout.
Шаг 3. Создание ограничений для одного представления
Давайте начнем с простого примера языка визуального формата. Для красного представления vwRed мы добавим ограничения Auto Layout, которые сделают его такого же размера, как и его суперпредставление. Это полезно в сценарии, где вы добавляете фоновое изображение.
Прежде чем использовать язык визуального формата, все слова, которые нам нужны, должны быть указаны в словаре. Вот как представления будут идентифицироваться языком визуального формата.
Создайте функцию с именем createConstraints с возвращаемым void типом в нижней части класса контроллера представления. Не беспокойтесь о синтаксисе. Мы еще createConstraints к createConstraints функции createConstraints .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
func createConstraints() -> Void
{
//Views to add constraints to
let views = Dictionary(dictionaryLiteral: («red»,vwRed),(«blue»,vwBlue),(«green»,vwGreen))
//Horizontal constraints
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(«H:|[red]|», options: nil, metrics: nil, views: views)
self.view.addConstraints(horizontalConstraints)
//Vertical constraints
let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(«V:|[red]|», options: nil, metrics: nil, views: views)
self.view.addConstraints(verticalConstraints)
}
|
Шаг 4: Сборка и запуск
Вызовите эту функцию в конце функции initViews мы создали ранее. Создайте и запустите проект, нажав Ctrl + R или нажав кнопку воспроизведения в левом верхнем углу. Симулятор iOS запустится, показывая красный вид, занимающий весь экран, как и предполагалось.

4. Анализ синтаксиса языка визуальных форматов
При использовании языка визуальных форматов ограничения автоматического макета определяются по горизонтали или по вертикали. Вы также можете определить высоту или ширину вида при объявлении вертикального и горизонтального ограничения соответственно. Давайте подробнее рассмотрим первую строку, которую мы использовали для создания горизонтального ограничения.
"H:|[red]|"
Сначала мы определяем, что это будет горизонтальное ограничение, начиная строку с буквы H По умолчанию используется горизонталь, но рекомендуется включить ее, чтобы сделать ее более очевидной. За направлением ограничения следует двоеточие.
| или символ трубы символизирует суперпредставление представления. Чтобы добавить пробел между двумя элементами, используется символ - или тире, и между ними можно поместить целочисленные значения, чтобы создать фиксированный или переменный интервал. На ссылки ссылаются ключи, предоставленные в словаре, переданные в constraintsWithVisualFormat . Каждый вид заключен в квадратные скобки.
Обратите внимание, как вся строка визуально соответствует изображению из симулятора. Это написано как предложение, которое будет читать что-то вроде: «По горизонтали красный вид должен расширять всю ширину своего суперпредставления без заполнения».
5. Создание ограничений для нескольких представлений
Теперь, когда у вас есть createConstraints представление о синтаксисе, мы собираемся отредактировать функцию createConstraints чтобы добавить ограничения Auto Layout для двух представлений.
Шаг 1: Редактировать горизонтальное ограничение
В функции createConstraints отредактируйте переменную horizontalConstraints как показано ниже.
|
1
2
3
|
//Horizontal constraints
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(«H:|-10-[red(>=100,<=200)]-0-[blue(==red)]-10-|», options: nil, metrics: nil, views: views)
self.view.addConstraints(horizontalConstraints)
|
Этот фрагмент кода действительно показывает гибкость языка визуальных форматов. Вышеприведенный оператор создает для нас ряд ограничений Auto Layout. Рядом с именем представления горизонтальные размеры определены в скобках. Для красного вида размер должен быть больше или равен 100 точкам, но меньше или равен 200 точкам.
Синий вид указывает, что он должен иметь такой же горизонтальный размер, как и красный вид, используя ==red в скобках. Это удобный способ указать, что несколько представлений должны иметь одинаковый размер. Создайте и запустите приложение в iOS Simulator. Результат должен выглядеть как на скриншоте ниже.

Шаг 2: Добавление приоритетов
Когда приложение запущено в симуляторе iOS, нажмите Ctrl + стрелка влево, чтобы изменить ориентацию симулятора iOS на альбомную. Пока приложение все еще работает нормально, в консоли Xcode появилось предупреждение. Предупреждение говорит нам, что некоторые ограничения Auto Layout не могут быть выполнены. Хотя это не приведет к сбою приложения, оно может привести к неожиданным результатам в пользовательском интерфейсе приложения.

Это происходит потому, что два созданных нами вида не могут иметь ширину 200 точек и не иметь промежутков между ними, когда устройство или симулятор iOS находятся в горизонтальной плоскости. Auto Layout решает эти типы сценариев, используя приоритеты. Язык визуального формата позволяет определять приоритеты с помощью символа @ . Отредактируйте переменную horizontalConstraints чтобы она читалась следующим образом:
|
1
2
|
//Horizontal constraints
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(«H:|-10-[red(>=100,<=200@20)]-0-[blue(==red)]-10-|», options: nil, metrics: nil, views: views)
|
Поскольку красные и синие представления теперь имеют низкий приоритет ограничения ширины, обозначенный @20 , система автоматической компоновки нарушит эти ограничения и предоставит им правильное значение во время выполнения. Запустите приложение еще раз и измените ориентацию на альбомную. Представления теперь заполняют дополнительное пространство, и XCode не производит никаких предупреждений.

Шаг 3. Добавление ограничений в вид снизу
Далее мы создадим ограничения для зеленого вида. Обновите реализацию функции createConstraints как показано ниже.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
func createConstraints() -> Void
{
//Views to add constraints to
let views = Dictionary(dictionaryLiteral: («red»,vwRed),(«blue»,vwBlue),(«green»,vwGreen))
//Horizontal constraints
let horizontalConstraintsRedBlue = NSLayoutConstraint.constraintsWithVisualFormat(«H:|-10-[red(>=100,<=200@20)]-0-[blue(==red)]-10-|», options: nil, metrics: nil, views: views)
self.view.addConstraints(horizontalConstraintsRedBlue)
let horizontalConstraintsGreen = NSLayoutConstraint.constraintsWithVisualFormat(«H:|[green]|», options: nil, metrics: nil, views: views)
self.view.addConstraints(horizontalConstraintsGreen)
//Vertical constraints
let verticalConstraintsRed = NSLayoutConstraint.constraintsWithVisualFormat(«V:|[red]-10-[green(40)]|», options: nil, metrics: nil, views: views)
self.view.addConstraints(verticalConstraintsRed)
let verticalConstraintsBlue = NSLayoutConstraint.constraintsWithVisualFormat(«V:|[blue]-10-[green(40)]|», options: nil, metrics: nil, views: views)
self.view.addConstraints(verticalConstraintsBlue)
}
|
Поскольку ограничение horizontalConstraintsGreen не определяет конкретную ширину или интервал для своего суперпредставления, оно будет охватывать всю длину. Вертикальное ограничение гарантирует, что оно будет 40 точек высотой с 10 точками расстояния между красным и синим видами.
Если вы запустите приложение еще раз, зеленый вид охватывает всю ширину экрана, а красный и синий вид останутся над ним, как и прежде. Когда симулятор iOS поворачивается в горизонтальное положение, представления сохраняют свои позиции и соответственно изменяют размер.

Шаг 4: Добавление метрик
Чтобы сделать все более читабельным, мы будем использовать словарь метрик в объявлениях ограничений. Создайте словарь, как показано ниже, сразу после объявления словаря представлений.
|
1
|
let metrics = Dictionary(dictionaryLiteral: («spacing», 10),(«lowWidth»,100),(«highWidth»,200),(«priority»,20),(«redBlueSpacing»,0),(«greenHeight»,40))
|
Теперь вместо использования жестко закодированных значений мы можем использовать значения словаря metrics , что делает объявления ограничений более читабельными. Отредактируйте функцию createConstraints последний раз, используя новый словарь metrics .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
func createConstraints() -> Void
{
//Views to add constraints to
let views = Dictionary(dictionaryLiteral: («red»,vwRed),(«blue»,vwBlue),(«green»,vwGreen))
//Metrics for Visual Format string
let metrics = Dictionary(dictionaryLiteral: («spacing», 10),(«lowWidth»,100),(«highWidth»,200),(«priority»,20),(«redBlueSpacing»,0),(«greenHeight»,40))
//Horizontal constraints
let horizontalConstraintsRedBlue = NSLayoutConstraint.constraintsWithVisualFormat(«H:|-spacing-[red(>=lowWidth,<=highWidth@priority)]-redBlueSpacing-[blue(==red)]-spacing-|», options: nil, metrics: metrics, views: views)
self.view.addConstraints(horizontalConstraintsRedBlue)
let horizontalConstraintsGreen = NSLayoutConstraint.constraintsWithVisualFormat(«H:|[green]|», options: nil, metrics: nil, views: views)
self.view.addConstraints(horizontalConstraintsGreen)
//Vertical constraints
let verticalConstraintsRed = NSLayoutConstraint.constraintsWithVisualFormat(«V:|[red]-spacing-[green(greenHeight)]|», options: nil, metrics: metrics, views: views)
self.view.addConstraints(verticalConstraintsRed)
let verticalConstraintsBlue = NSLayoutConstraint.constraintsWithVisualFormat(«V:|[blue]-spacing-[green(greenHeight)]|», options: nil, metrics: metrics, views: views)
self.view.addConstraints(verticalConstraintsBlue)
}
|
6. Ограничения языка визуального формата
Вы можете быть удивлены, почему высота зеленого вида была определена дважды. Это потому, что язык визуального формата работает в строках и столбцах. При использовании языка визуальных форматов подумайте о добавлении ограничений слева направо на одну «строку» представления для горизонтальных ограничений. Для вертикальных ограничений вы должны думать о столбцах.
Большинство ограничений Auto Layout, которые вы будете использовать, могут быть выражены с помощью языка визуального формата. Однако есть некоторые, которые не могут. Например, ограничение фиксированного соотношения сторон не может быть создано с использованием языка визуального формата. Это не может быть выполнено с помощью синтаксиса Visual Format Language, потому что следующая строка не может быть проанализирована:
H:|imageView.width = 2 * imageView.height|
Вы все еще можете использовать Auto Layout в своем коде для достижения этих типов ограничений, используя традиционный метод constraintWithItem .
Вывод
Язык визуального формата может быть очень полезен, когда вам нужно создать ограничения Auto Layout в коде. Вместо того, чтобы создавать ограничения одно за другим, язык визуального формата позволяет создавать ряд ограничений с помощью одной строки кода.
До того, как Auto Layout был доступен для разработчиков, отслеживание того, как изменить размеры представлений для различных категорий устройств, было большой работой. Благодаря Auto Layout и Visual Format Language это стало более интуитивно понятным, что упрощает поддержку пользовательских интерфейсов на всех устройствах.