SA0603 — Прототипирование основного вида iOS приложения
Содержание страницы
А теперь самое интересное! В этой главе вы приступите к созданию прототипа вашего приложения, которое имеет четыре полноэкранных режима просмотра:
- Добро пожаловать
- Упражнение
- История
- Успех
Создание представления упражнения
Вы начнете с размещения представления упражнения, потому что оно содержит наибольшее количество вложенных представлений. Вот список того, что ваш пользователь видит в этом представлении:
- Заголовок и номера страниц находятся в верхней части представления, а кнопка Истории — в нижней части.
- Номера страниц указывают на наличие четырех пронумерованных страниц.
- Вид упражнения содержит видеопроигрыватель, таймер, кнопку запуска / завершения и символы оценки.
А вот список, переписанный как список вложенных представлений:
- Заголовок с номерами страниц
- Видеоплеер
- Таймер
- Кнопка «Начать/Готово»
- Оценка
- Кнопка Истории
Вы можете создавать эскизы своих экранов в приложении, таком как Sketch или Figma, прежде чем переводить проекты в представления SwiftUI. Но SwiftUI позволяет легко размещать представления непосредственно в вашем проекте, так что это то, что вы будете делать.
Прелесть SwiftUI в том, что он декларативный: вы просто объявляете представления, которые хотите отобразить, в том порядке, в котором вы хотите, чтобы они отображались. Если вы создали веб-страницы, это похожий опыт.
Обрисовывая в общих чертах вид упражнения
➤ Продолжайте работу с вашим проектом из предыдущей главы или откройте проект в начальной папке этой главы.
В этом представлении предстоит многое сделать, поэтому вы начнете с создания контура с Text
представлениями-заполнителями.
➤ Откройте ExerciseView.swift.
➤ В режиме предварительного просмотра холста по умолчанию используется имитируемое устройство назначения запуска. Вы начнете с разработки интерфейса для iPad-версии HIITFit, поэтому выберите симулятор для iPad:

➤ Если iPad не помещается на холсте, уменьшите масштаб:

➤ ExerciseView
имеет шесть вложенных представлений, поэтому продублируйте Text(exerciseNames[index])
представление, затем отредактируйте аргументы — в коде или в холсте — чтобы создать этот список.:
VStack {
Text(exerciseNames[index])
Text("Video player")
Text("Timer")
Text("Start/Done button")
Text("Rating")
Text("History button")
}
Первый Text
вид является отправной точкой для представления заголовка. Вы создадите представления заголовка и рейтинга в их собственных файлах. Видеоплеер, таймер и кнопки представляют собой простые виды, поэтому вы просто создадите их непосредственно в ExerciseView
нем.
Создание представления заголовка
Навыки, которые вы изучите в этом разделе: изменение представлений с помощью инспектора атрибутов или автоматического предложения; подписи методов с именами внутренних и внешних параметров; использование символов SF;
Image
просмотр; извлечение и настройка вложенных представлений; работа с предварительными просмотрами
Вы создадите это представление заголовка, добавив в него кодExerciseView
, затем извлекете его как вложенное представление и переместите в его собственный файл.
➤ Чтобы подготовиться к последующему извлечению, внедрите первое Text
представление в aVStack
: удерживая нажатой клавишу Command, нажмите Text(exerciseNames[index])
затем выберите Внедрить в VStack:

Примечание: Эта версия меню командной строки отображается только тогда, когда холст открыт. Если вы не видите опцию Встроить в VStack, нажмите Option-Command-Return, чтобы открыть холст.
Теперь это Text
представление находится внутриVStack
:
VStack {
Text(exerciseNames[index])
}
Множество способов изменения представления
➤ На холсте выберите вид “Приземистый”Text
. Чтобы открыть инспектор атрибутов, нажмите кнопку инспекторы на панели инструментов, затем выберите Инспектор атрибутов:

В этом инспекторе есть разделы для наиболее часто используемых модификаторов: шрифт, Заполнение и Рамка. Вы можете выбрать размер шрифта в меню Шрифт ▸ Шрифт, но на этот раз вы будете использовать поле поиска. Это более общий подход к добавлению модификаторов.
➤ Щелкните в поле Добавить модификатор, затем введите шрифт и выберите Шрифт из меню:

Размер шрифта “Squat” изменяется как на холсте, так и в коде:
.font(.title)
➤ Xcode предлагает размер шрифтаtitle
, но это всего лишь заполнитель. Чтобы “принять” это значение, нажмите.title
, а затем нажмите Return, чтобы установить его в качестве значения.
Примечание: Xcode и SwiftUI хорошо справляются с автоматическим предложением или выбором по умолчанию параметра, который, вероятно, является тем, что вам нужно.
➤ Чтобы просмотреть другие параметры, щелкните элемент управления-Опция- font
или title
. Откроется font
всплывающий инспектор атрибутов модификатора. В разделе Шрифт щелкните заголовок выбранного варианта шрифта, чтобы открыть меню Шрифт:

➤ Выберите Большой заголовок в меню: теперь “Присед” еще больше!

Примечание: помещение модификатора в его собственную строку является соглашением SwiftUI. Представление часто имеет несколько модификаторов, каждый в своей отдельной строке. Это упрощает перемещение модификатора вверх или вниз, потому что иногда порядок имеет значение.
➤ Вот еще один способ просмотра font
меню. Выберите .largeTitle
и замените его на . — Стандартный механизм автоматического предложения Xcode перечисляет возможные значения:

➤ Выберите Большой заголовок в меню.
➤ Как только вы познакомитесь с модификаторами SwiftUI, вы можете предпочесть просто ввести. Удалите .font(.largeTitle)
и введите .шрифт. Xcode автоматически предлагает два font
метода:

➤ Выберите любой метод, и Xcode автоматически завершится с (.title)
помощью . Измените это на .Большой заголовок.
Быстрый совет: сигнатура метода
func font(_ font: Font?) -> Text
указывает, что этот метод принимает один параметр типаFont?
и возвращаетText
представление. “_” означает, что нет имени внешнего параметра — вы вызываете его сfont(.title)
помощью, а не сfont(font: .title)
помощью .
Создание номеров страниц
В дополнение к названию упражнения в заголовке должны отображаться номера страниц с выделенным текущим номером страницы. Это заменяет TabView
указательные точки.
Вы могли бы просто отображать Text("1")
Text("2")
и так далее, но Apple предоставляет множество настраиваемых значков в качестве символов SF.
➤ Приложение SF Symbols — это лучший способ просмотра и поиска в коллекции. Загрузите и установите его с apple.co/3hWxn3G . Некоторые символы должны использоваться только для определенных продуктов Apple, таких как FaceTime или AirPods. Вы можете проверить символы на наличие ограничений по адресу sfsymbols.com .
➤ После установки приложения SF Symbols откройте его и выберите категорию Indexes. Прокрутите вниз до цифр:

Вы можете выбрать черные цифры на белом фоне или наоборот, в виде круга или квадрата. Заполненная версия — хороший выбор для представления текущей страницы с номерами без заполнения для других страниц.
➤ Названия символов SF могут быть длинными, но их легко скопировать из приложения. Выберите символ, затем откройте меню редактирования приложения:

Примечание: Сочетание клавиш — Shift-Command-C.
➤ Выберите символ “1.круг” без заполнения, нажмите Shift-Command-C, затем используйте название, чтобы добавить эту строку кода под заголовкомText
:
Image(systemName: "1.circle")
Image
это еще одно встроенное представление SwiftUI, и оно имеет инициализатор, который принимает имя символа SF как a String
.
➤ Перед добавлением дополнительных чисел щелкните Image
по нему, чтобы вставить его в an HStack
, чтобы числа отображались рядом. Затем продублируйте и отредактируйте больше Image
представлений, чтобы создать остальные три числа:
HStack {
Image(systemName: "1.circle")
Image(systemName: "2.circle")
Image(systemName: "3.circle")
Image(systemName: "4.circle")
}
И вот ваш заголовок:

Номера страниц выглядят слишком маленькими. Поскольку символы SF интегрированы в системный шрифт San Francisco — это “SF” в символах SF — вы можете обрабатывать их как текст и использовать font
для указания их размера.
➤ Вы можете добавлять .font(.title)
в каждыйImage
, но быстрее и аккуратнее добавлять его в HStack
контейнер:
HStack {
Image(systemName: "1.circle")
Image(systemName: "2.circle")
Image(systemName: "3.circle")
Image(systemName: "4.circle")
}
.font(.title2)
Размер шрифта применяется ко всем представлениям вHStack
:

➤ Вы можете изменить anImage
, чтобы переопределить HStack
модификатор. Например, измените первое число, чтобы сделать его более крупным:
Image(systemName: "1.circle")
.font(.largeTitle)
Теперь только первый символ больше:

➤ Удалите Image
модификатор, чтобы все числа были одинакового размера.
ExerciseView
Теперь у вас есть заголовок, который вы будете использовать повторноWelcomeView
. Итак, вы собираетесь извлечь код заголовка для создания HeaderView
.
Вы будете использовать инструмент рефакторинга Xcode, который работает хорошо. Но всегда полезно зафиксировать свой код перед подобным изменением, на всякий случай. Выберите Управление версиями ▸ Зафиксировать… или нажмите Option-Command-C.
Извлечение вложенного представления
Хорошо, барабанная дробь …
➤ Команда -щелкните значокVStack
, содержащий заголовок Text
и номера страницHStack
, затем выберите в меню пункт Извлечь вложенный просмотр:

Xcode перемещает целое VStack
в body
свойство нового представления с именем заполнителя ExtractedView
. И ExtractedView()
находится там, где VStack
раньше было:

➤ Пока заполнители все еще выделены, введите headerView и нажмите Return. Если вы упустите момент, просто отредактируйте оба заполнителя.
Флаг ошибки показывает, где вам нужен параметр. index
Свойство является локальнымExerciseView
, поэтому вы не можете использовать егоHeaderView
. Вы могли бы просто перейти index
к HeaderView
и убедиться, что он может получить доступ к exerciseNames
массиву. Но всегда лучше передавать достаточно информации. Это упрощает настройку предварительного просмотра для HeaderView
. Прямо сейчас HeaderView
требуется только название упражнения.
➤ Добавьте это свойство в HeaderView
, над свойством body:
let exerciseName: String
➤ И заменить exerciseNames[index]
вText
:
Text(exerciseName)
➤ Прокрутите доExerciseView
, где Xcode жалуется на пропущенный аргумент в HeaderView()
. Щелкните значок ошибки, чтобы нажать Исправить, затем заполните строку, чтобы прочитать:
HeaderView(exerciseName: exerciseNames[index])
➤ Теперь нажмите Command-N, чтобы создать новый файл представления SwiftUI и назовите его headerView.swift. Поскольку вы находились в ExerciseView.swift, когда нажали Command-N, новый файл появится под ним и в той же папке группы.
Ваш новый файл открывается в редакторе с двумя флагами ошибок:
- Недопустимое повторное объявление ’headerView’.
- Отсутствует аргумент для параметра ’exerciseName’.
➤ Чтобы исправить первое, в ExerciseView.swift выделите все 17 строк вашего нового HeaderView
файла и нажмите Command-X, чтобы вырезать его — скопируйте его в буфер обмена и удалите из ExerciseView.swift.
➤ Вернувшись в headerView.swift, замените 5-строчный шаблон HeaderView
тем, что находится в буфере обмена.
➤ Чтобы исправить вторую ошибку, в previews
, пусть Xcode добавит отсутствующий параметр, затем введите любое имя упражнения для аргумента:
HeaderView(exerciseName: "Squat")
Поскольку вы передаете только название упражненияHeaderView
, для предварительного просмотра не требуется доступ к exerciseNames
массиву.
Работа с превью
Предварительный просмотр по-прежнему использует симулятор iPad, который занимает много места. Вы можете изменить предварительный просмотр, чтобы показывать только заголовок.
➤ В HeaderView_Previews
, Control-Option-щелкните HeaderView(...)
, затем введите предварительный просмотр в поле Добавить модификатор:

➤ Выберите Предварительный просмотр макета, чтобы добавить этот модификатор:
.previewLayout(.sizeThatFits)
➤ Значение заполнителя равно sizeThatFits
, и это то, что вы хотите, но вы должны “принять” его. Нажмите sizeThatFits, затем нажмите Return, чтобы установить его в качестве значения.
➤ Возобновите предварительный просмотр, чтобы увидеть только заголовок.:

➤ Теперь вы готовы увидеть всю мощь предварительного просмотра. На холсте предварительного просмотра нажмите кнопку Дублировать предварительный просмотр:

Вы сделали копию предварительного просмотра на холсте и в коде:
Group {
HeaderView(exerciseName: "Squat")
.previewLayout(.sizeThatFits)
HeaderView(exerciseName: "Squat")
.previewLayout(.sizeThatFits)
}
Точно так же, как при дублировании Text
представления, Xcode встраивает два представления в представление контейнера. На этот раз это a Group
, который ничего не указывает о макете. Его единственная цель — объединить несколько представлений в одно представление.
Быстрый совет: свойства
body
иpreviews
являются вычисляемыми свойствами. Они должны возвращать значение типаsome View
, поэтому то, что находится внутри замыкания, должно быть единым представлением.
➤ Теперь вы можете изменить второй предварительный просмотр. Нажмите на его кнопку предварительного просмотра:

Инспектор позволяет задать цветовую схему и динамический тип.
➤ Установите цветовую схему на темную, а динамический тип — на accessibilityLarge.

Вот как легко увидеть, как это представление отображается на устройстве с такими настройками.
Теперь вернитесь к ExerciseView.swift, где заголовок будет таким, каким вы его оставили.

Время для повторной фиксации изменений: Выберите Управление версиями ▸ Зафиксировать … или нажмите Option-Command-C. И это последний раз, когда я тебе напоминаю. ;]
Затем вы настроите видеопроигрыватель.
Воспроизведение видео
Навыки, которые вы изучите в этом разделе: использование
AVPlayer
иVideoPlayer
; использование файлов пакетов; необязательные типы; создание условий; использованиеGeometryReader
; добавление отступов
➤ В ExerciseView.swift добавьте это утверждение чуть нижеimport SwiftUI
:
import AVKit
AVKit
является основой в наборах Apple для разработки программного обеспечения (SDK). Импортируя его, вы можете использовать высокоуровневые типы, напримерAVPlayer
, для воспроизведения видео с обычными элементами управления воспроизведением.
➤ Теперь замените Text("Video player")
на эту строку:
VideoPlayer(player: AVPlayer(url: url))
Xcode жалуется, что “не может найти ”url» в области видимости», поэтому вы определите это значение следующим.
Получение URL-адреса файла пакета
Для этого упражнения вам понадобится URL-адрес видеофайла. В videonames
массиве отображается часть имен файлов. Все файлы имеют расширение .mp4.
Эти файлы находятся в папке проекта, к которой вы можете получить доступ как Bundle.main
. Его метод url(forResource:withExtension:)
возвращает вам URL-адрес файла в основном пакете приложений, если он существует. В противном случае он возвращаетnil
, что означает отсутствие значения. Возвращаемый тип этого метода — это Optional
тип, URL?
.
Совет по Swift:
Optional
тип Swift помогает избежать многих труднодоступных ошибок, распространенных в других языках программирования. Обычно он объявляется как тип типаInt
илиString
, за которым следует вопросительный знак:Int?
илиString?
. Если вы объявитеvar index: Int?
,index
может содержатьInt
или вообще не содержать значения. Если вы объявляетеvar index: Int
— с no?
—index
всегда должно содержатьInt
. Используетсяif let index = index {...}
для проверки, имеет ли необязательный параметр значение. Справаindex
от=
является необязательным значением. Если у него есть значение, тоindex
слева от=
него находится anInt
, а условие равноtrue
. Если необязательный параметр не имеет значения, присвоение=
не выполняется и условие выполняетсяfalse
. Вы также можете проверитьindex != nil
, который возвращаетtrue
, еслиindex
имеет значение.
Примечание: Вы узнаете больше о пакете приложений в главе 8 “Сохранение настроек”, а о дополнительных функциях — в главе 9 “Сохранение исторических данных”.
Итак, вам нужно обернуть if let
вокругVideoPlayer
. Еще одна пара брекетов! Может быть трудно уследить за ними всеми. Но Xcode здесь, чтобы помочь. ;]
➤ Щелкните правой кнопкой мыши VideoPlayer
и выберите Сделать условным. И есть if
else
упаковка для закрытия VideoPlayer
!
Совет по Xcode: воспользуйтесь преимуществами таких функций, как встраивание в HStack, и сделайте условным, чтобы Xcode поддерживал соответствие фигурных скобок. Чтобы изменить то, что включено в закрытие, используйте Option-Command-[ или Option-Command-], чтобы переместить закрывающую фигурную скобку вверх или вниз.
➤ Теперь замените if true {
на:
if let url = Bundle.main.url(
forResource: videoNames[index],
withExtension: "mp4") {
➤ В else
закрытии заменить EmptyView()
на:
Text("Couldn’t find \(videoNames[index]).mp4")
.foregroundColor(.red)
Быстрый совет: код интерполяции строк
\(videoNames[index])
вставляет значениеvideoNames[index]
в строковый литерал.
➤ Протестировать этот else
код легко: создайте опечатку, изменив withExtension
аргумент на np4, затем обновите предварительный просмотр:

На самом деле, это squat.n p4, которого нет в пакете приложений.
➤ Исправьте np4
опечатку.
➤ Теперь нажмите Предварительный просмотр в реальном времени, затем нажмите кнопку воспроизведения, чтобы просмотреть видео. Если кнопка воспроизведения исчезает, попробуйте сделать следующее: нажмите на видео, затем нажмите Пробел.
Получение размеров экрана
Видео занимает много места на экране. Вы можете установить ширину и высоту его рамки на некоторые постоянные значения, которые работают на большинстве устройств, но лучше, если эти измерения будут адаптированы к размеру устройства.
➤ Вbody
, щелкните правой кнопкой мыши VStack
и выберите Вставить.… Замените Container {
заполнитель на эту строку:
GeometryReader { geometry in
GeometryReader
это контейнерное представление, которое предоставляет вам измерения экрана для любого устройства, которое вы просматриваете или на котором работаете.
➤ Добавьте этот модификатор вVideoPlayer
:
.frame(height: geometry.size.height * 0.45)
Видеоплеер теперь использует только 45% высоты экрана:

Добавление отступов
➤ Заголовок выглядит немного раздавленным. Элемент управления-Опция-нажмите HeaderView
, чтобы добавить padding
в его нижней части:

Это дает вам новый модификаторpadding(.bottom)
, и теперь между заголовком и видео есть пробел:

Примечание: вы могли бы добавить отступы
VStack
в файл headerView.swift, ноHeaderView
он немного более удобен для повторного использования без отступов. Вы можете выбрать, следует ли добавлять отступы и как их настраивать при использованииHeaderView
в другом представлении.
Теперь вернитесь в contentView.swift и просмотрите свое приложение в режиме реального времени. Проведите пальцем от одной страницы к следующей, чтобы просмотреть различные видеоролики с упражнениями.

Завершение просмотра упражнения
Навыки, которые вы изучите в этом разделе:
Text
с параметрами даты и стиля; типы в Swift;Date()
;Button
,Spacer
,foregroundColor
; повторение представления; неиспользуемый параметр закрытия
Чтобы завершить просмотр упражнений, добавьте таймер и кнопки, а затем создайте просмотр оценок.
Создание представления таймера
➤ Добавьте это свойство в ExerciseView
, вышеbody
:
let interval: TimeInterval = 30
Это интервальные упражнения высокой интенсивности, поэтому таймер отсчитывает время с 30 секунд.
➤ Заменить Text("Timer")
на этот код:
Text(Date().addingTimeInterval(interval), style: .timer)
.font(.system(size: 90))
Инициализатор по умолчанию Date()
создает значение с текущей датой и временем. Date
Метод addingTimeInterval(_ timeInterval:)
добавляет interval
секунды к этому значению.
➤ Date
Тип Swift имеет множество методов для манипулирования значениями даты и времени. Выберите опцию Date
и откройте в Документации разработчика, чтобы просмотреть все, что доступно. Вы погрузитесь немного глубжеDate
, когда создадите представление истории.
Тип timeInterval
параметра TimeInterval
равен . Это просто псевдоним для Double
. Если вы скажетеinterval
, что имеет типDouble
, вы не получите ошибку, но TimeInterval
более точно опишете назначение значения.
Совет по Swift: Swift — это строго типизированный язык. Это означает, что вы должны использовать правильный тип. При использовании чисел обычно можно передать значение неправильного типа инициализатору правильного типа. Например,
Double(myIntValue)
создаетDouble
значение из anInt
иInt(myDoubleValue)
усекаетDouble
значение для создания anInt
. Если вы пишете код на языках, допускающих автоматическое преобразование, легко создать ошибку, которую очень трудно найти. Swift гарантирует, что вы и люди, читающие ваш код, знаете, что вы преобразуете один тип в другой.
Вы используете инициализатор Text
представления (_:style:)
для отображения дат и времени. Стили timer
и relative
отображают интервал времени между текущим временем и date
значением в формате “mm:ss” или “mm min ss sec” соответственно. Эти два стиля обновляют отображение каждую секунду.
Вы устанавливаете размер системного шрифта на 90 пунктов, чтобы создать действительно большой таймер.
➤ Нажмите Предварительный просмотр в реальном времени, чтобы просмотреть обратный отсчет таймера с 30 секунд:

Поскольку вы установили date
значение 30 секунд в будущем, отображаемый интервал времени уменьшается на 1 каждую секунду по мере приближения к текущему времени date
. Если вы подождете, пока он не достигнет 0 (измените interval
на 3, чтобы вам не пришлось ждать так долго), вы увидите, что он начинает отсчет, поскольку текущее время удаляетсяdate
. Не волнуйтесь, этот Text
таймер предназначен только для прототипа. Вы замените его реальным таймером в главе 7 “Наблюдение за объектами”.
Создание кнопок
Создание кнопок простое, так что теперь вы сделаете и то, и другое.
➤ Заменить Text("Start/Done button")
на этот код:
Button("Start/Done") { }
.font(.title3)
.padding()
Здесь вы дали Button
ярлык Start / Done и пустое действие. Вы добавите действие в главе 7 “Наблюдение за объектами”. Затем вы увеличили шрифт его метки и добавили отступы вокруг него.
➤ Заменить Text("History button")
на этот код:
Spacer()
Button("History") { }
.padding(.bottom)
Spacer
Нажимает кнопку истории в нижней части экрана. Это padding
немного отодвигает его назад, чтобы он не выглядел раздавленным.
Вы добавите действие этой кнопки в главе 6 “Добавление функциональности в ваше приложение”.
Вот как ExerciseView
это выглядит сейчас:

Теперь перейдем к последнему подразделу в ExerciseView
разделе : RatingView
.
Создание рейтингового представления
➤ Создайте новый файл представления SwiftUI с именем RatingView.swift. Это будет небольшое представление, поэтому добавьте этот модификатор в его предварительный просмотр:
.previewLayout(.sizeThatFits)
Рейтинг обычно равен пяти звездам или сердечкам, но оценка упражнения должна отражать усилия пользователя.
➤ Чтобы найти более подходящий символ рейтинга, откройте приложение SF Symbols и выберите категорию здоровья:

➤ Форма волны ЭКГ кажется подходящей для оценки упражнений высокой интенсивности! Выберите его, затем нажмите Shift-Command-C, чтобы скопировать его имя.
➤ Замените шаблон Text
этим кодом, вставив название символа между двойными кавычками:
Image(systemName: "waveform.path.ecg")
.foregroundColor(.gray)
Вы добавили символ SF в качестве символа Image
и установили для него серый цвет.
Для представления рейтинга требуется пять таких символов, расположенных горизонтально.
➤ На холсте или в редакторе щелкните правой кнопкой мыши Image
и выберите Повторить в меню:

Xcode дает вам цикл с предлагаемым диапазоном0 ..< 5
:
ForEach(0 ..< 5) { item in
Image(systemName: "waveform.path.ecg")
.foregroundColor(.gray)
}
➤ Щелкните этот диапазон и нажмите Return, чтобы принять его.
На холсте вы видите пять отдельных превью! Xcode должен был встроить их в стек, например, когда вы дублировали представление, но этого не произошло.
➤ Щелкните правой кнопкой мыши ForEach
и вставьте его в HStack
.
Теперь ваш код выглядит следующим образом:
HStack {
ForEach(0 ..< 5) { item in
Image(systemName: "waveform.path.ecg")
.foregroundColor(.gray)
}
}
Так-то лучше! Теперь все символы расположены в ряд. Но они очень маленькие.

➤ Помните, что вы можете использовать font
для указания размера символов SF. Итак, добавьте этот модификатор вImage
:
.font(.largeTitle)
Чем больше, тем лучше!

И последняя деталь: созданный для вас код Xcode содержит неиспользуемый параметр закрытия item
:
ForEach(0 ..< 5) { item in
➤ Вы не используете item
в цикле код, поэтому замените item
на_
:
ForEach(0 ..< 5) { _ in
Совет по Swift: хорошей практикой программирования является замена неиспользуемых имен параметров на
_
. Альтернативой является создание одноразового имени, которое отнимает ненулевое количество времени и внимания и сбивает с толку вас и других программистов, читающих ваш код.
➤ Теперь вернитесь в ExerciseView.swift, чтобы использовать свой новый вид. Замените Text("Rating")
на этот код:
RatingView()
.padding()
Ваши волновые формы ЭКГ теперь маршируют по экрану!

В главе 6 “Добавление функциональности в ваше приложение” вы добавите код, позволяющий пользователю устанавливать значение рейтинга и представлять это значение, устанавливая нужное количество символов красным цветом. А в главе 8 “Сохранение настроек” вы сохраните значения рейтинга, чтобы они сохранялись при запуске приложения.
Ключевые моменты
- SwiftUI является декларативным: просто объявляйте представления в том порядке, в котором вы хотите, чтобы они отображались.
- Создайте отдельные представления для элементов вашего пользовательского интерфейса. Это упрощает чтение и поддержку вашего кода.
- Используйте соглашение SwiftUI о размещении каждого модификатора в отдельной строке. Это упрощает перемещение или удаление модификатора.
- Xcode и SwiftUI предоставляют автоматические предложения и значения по умолчанию, которые часто являются тем, что вам нужно.
- Пусть Xcode поможет вам избежать ошибок: используйте Командное меню, чтобы встроить представление в стек или в
if-else
замыкание, или извлечь представление в подвиде. - Приложение SF Symbols предоставляет изображения значков, которые вы можете настроить как текст.
- Предварительный просмотр — это простой способ проверить, как выглядит ваш интерфейс при различных пользовательских настройках.
- Swift — это строго типизированный язык программирования.
GeometryReader
позволяет задать размеры представления относительно размеров экрана.
Куда идти дальше?
Ваше представление упражнения готово. В следующей главе вы расскажете о трех других полноэкранных режимах, необходимых вашему приложению.