Жизненный цикл приложения на Swift
Создание проекта и структура приложения
Инициализация проекта в Xcode
Создание нового проекта на Swift начинается с запуска Xcode и выбора опции "Create a new Xcode project". Xcode предоставляет различные шаблоны приложений — App, Game, Augmented Reality App, Document App, Framework, Package. Для стандартного приложения используется шаблон "App".
При создании проекта указываются следующие параметры:
- Название продукта
- Команда разработки
- Идентификатор организации
- Интерфейс (Storyboard или SwiftUI)
- Язык программирования (Swift или Objective-C)
- Поддержка Core Data
- Включение тестирования
Пример конфигурации нового проекта:
Код ITЗагрузка примера кода…
Разбор:
- Это манифест Swift Package Manager, который описывает пакет и правила сборки.
platformsфиксирует минимальную версию iOS, с которой совместим код.productsопределяют, что именно экспортируется наружу (библиотека/исполняемый модуль).targetsзадают единицы компиляции и их зависимости.
Структура каталогов проекта
Стандартная структура проекта Xcode включает следующие основные каталоги:
MyApplication/
├── MyApplication/
│ ├── Assets.xcassets/
│ ├── Base.lproj/
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── AppDelegate.swift
│ ├── SceneDelegate.swift
│ └── ViewController.swift
├── MyApplication.xcodeproj/
├── MyApplicationTests/
└── MyApplicationUITests/
Каталог Assets.xcassets содержит все изображения, цвета, шрифты и другие ресурсы приложения. Base.lproj содержит файлы интерфейса. AppDelegate.swift и SceneDelegate.swift управляют жизненным циклом приложения.
Конфигурационные файлы проекта
Файл Info.plist содержит метаданные приложения — идентификатор пакета, версия, необходимые разрешения, поддерживаемые ориентации устройства. Современные версии Xcode позволяют использовать Swift-код для конфигурации вместо XML-формата.
// Пример конфигурации через Swift
@main
struct MyApplicationApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Разбор:
@mainпомечает главный тип приложения и точку входа.- Протокол
Appиспользуется в SwiftUI-жизненном цикле вместо классическогоAppDelegate-старта. WindowGroupсоздаёт сцену окна, где корневым представлением становитсяContentView.
Точка входа приложения
Функция main и @main атрибут
В традиционных языках программирования точкой входа служит функция main. В Swift для приложений iOS используется атрибут @main, который автоматически генерирует точку входа. Этот подход появился в Swift 5.3 и значительно упростил структуру приложения.
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
}
Разбор:
UIApplicationDelegateполучает ключевые события старта и состояния приложения.- Метод
didFinishLaunchingWithOptionsвызывается после запуска инициализации приложения. - Возврат
trueподтверждает успешный запуск для системы.
Атрибут @main указывает компилятору, что данный класс или структура является основной точкой входа приложения. До появления @main требовалась явная функция main в отдельном файле.
Роль класса AppDelegate
Класс AppDelegate управляет глобальными событиями приложения — запуск, переход в фоновый режим, возврат в активное состояние, завершение работы. Все методы делегата вызываются системой в определенном порядке.
Код ITЗагрузка примера кода…
Разбор:
- Пример показывает полный набор методов жизненного цикла приложения UIKit.
- Методы
applicationDidBecomeActive/applicationDidEnterBackgroundотмечают переходы между foreground/background. - В каждую точку обычно выносят соответствующие операции — запуск задач, пауза, сохранение данных.
Жизненный цикл приложения
Состояния приложения
Приложение iOS проходит через пять основных состояний в течение своего жизненного цикла:
Not Running — приложение не запущено или было завершено системой. Это начальное состояние до первого запуска или после полного завершения работы.
Inactive — приложение работает в фоновом режиме, но не получает события. Это состояние возникает при переходе между активным и фоновым режимами, при получении уведомлений, входящих вызовов.
Active — приложение работает на переднем плане и получает все события. Это основное рабочее состояние, когда пользователь взаимодействует с интерфейсом.
Background — приложение выполняется в фоновом режиме и может выполнять ограниченные задачи. Система предоставляет несколько минут для завершения операций.
Suspended — приложение находится в фоновом режиме, но не выполняет код. Система приостанавливает приложение для экономии ресурсов.
Последовательность методов жизненного цикла
При первом запуске приложения система вызывает методы в следующем порядке:
Код ITЗагрузка примера кода…
Разбор:
- Блок показывает последовательность запуска: ранняя инициализация -> финальная конфигурация -> переход в active.
setupCoreServices/configureAppearance/setupNavigationдемонстрируют распределение ответственности по этапам.applicationDidBecomeActive— точка, где допустимо возобновлять интерактивные задачи.
При переходе в фоновый режим вызываются методы:
Код ITЗагрузка примера кода…
Разбор:
- Эти методы обрабатывают уход приложения в фон.
- В
willResignActiveвыполняется пауза текущих задач и подготовка состояния. beginBackgroundTaskвdidEnterBackgroundзапрашивает ограниченное время на завершение критичных операций.
При возврате в активное состояние:
func applicationWillEnterForeground(_ application: UIApplication) {
// Подготовка к активному состоянию
restoreState()
checkForUpdates()
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Полное восстановление активности
resumeTasks()
refreshInterface()
}
Разбор:
- При возврате из фона сначала идёт подготовка (
restoreState,checkForUpdates), затем полное восстановление активности. - Такой порядок помогает избежать гонок и неполного восстановления UI.
- Разделение по методам делает поведение приложения предсказуемым при смене состояний.
SceneDelegate и многозадачность
Начиная с iOS 13, Apple ввела концепцию сцен (scenes) для поддержки многозадачности на iPad и других устройствах. SceneDelegate управляет жизненным циклом отдельных окон приложения.
Код ITЗагрузка примера кода…
Разбор:
SceneDelegateуправляет отдельным окном/сценой, что важно для многосценарности iPadOS.- В
willConnectToсоздаётсяUIWindow, назначается root-контроллер и окно делается видимым. - Остальные методы отражают lifecycle конкретной сцены, а не всего приложения.
Жизненный цикл представлений
Состояния жизненного цикла ViewController
Каждый ViewController проходит через серию состояний при загрузке, отображении и удалении. Понимание этих состояний критически важно для правильного управления ресурсами и данными.
Loaded — представление загружено в память, но еще не отображено на экране. Метод viewDidLoad вызывается один раз при создании представления.
Appeared — представление полностью отображено и видимо пользователю. Метод viewDidAppear вызывается каждый раз при появлении представления.
Disappeared — представление скрыто, но остается в памяти. Метод viewDidDisappear вызывается при скрытии представления.
Unloaded — представление удалено из памяти. Система освобождает ресурсы при нехватке памяти или при явном удалении.
Методы жизненного цикла ViewController
Код ITЗагрузка примера кода…
Разбор:
- Показаны ключевые методы lifecycle экрана — загрузка, показ, скрытие, перерасчёт layout, реакция на memory warning.
viewDidLoadподходит для одноразовой настройки,viewWillAppear/viewDidAppear— для обновления перед показом и после него.viewWillDisappear/viewDidDisappear— точки остановки задач и освобождения ресурсов.
Порядок вызова методов при навигации
При переходе между представлениями система вызывает методы в определенном порядке. Понимание этой последовательности помогает правильно управлять состоянием и ресурсами.
При показе нового представления:
Старый контроллер:
- viewWillDisappear
- viewDidDisappear
Новый контроллер:
- viewDidLoad
- viewWillAppear
- viewDidAppear
При возврате к предыдущему представлению:
Текущий контроллер:
- viewWillDisappear
- viewDidDisappear
Предыдущий контроллер:
- viewWillAppear
- viewDidAppear
Управление памятью в жизненном цикле
Swift использует автоматическое подсчет ссылок (ARC) для управления памятью. Понимание жизненного цикла помогает избежать утечек памяти и сильных ссылочных циклов.
Код ITЗагрузка примера кода…
Разбор:
- Пример связывает lifecycle экрана с управлением ресурсами и наблюдателями.
- Подписки добавляются в
setupObservers()с[weak self], чтобы не создавать retain cycle. - В
viewWillDisappearиviewDidDisappearостанавливаются фоновые операции и удаляются observers. deinitподтверждает освобождение контроллера и выполняет финальную очистку.
Управление фоновыми задачами
Типы фоновых операций
iOS поддерживает несколько типов фоновых операций, каждая со своими ограничениями и временем выполнения.
Background Fetch — периодическая загрузка данных в фоновом режиме. Система определяет оптимальное время для выполнения операций.
Код ITЗагрузка примера кода…
Разбор:
- Включается Background Fetch через
setMinimumBackgroundFetchInterval. - Метод
performFetchWithCompletionHandlerобязан вызвать completion с результатом (newData,noData,failed). - Корректный completion помогает системе планировать будущие фоновые запуски.
Background Processing — длительные задачи, требующие дополнительного времени. Система предоставляет до 3 минут для завершения операций.
func performBackgroundTask() {
var task: UIBackgroundTaskIdentifier = .invalid
task = UIApplication.shared.beginBackgroundTask {
UIApplication.shared.endBackgroundTask(task)
task = .invalid
}
processLargeFile { _ in
UIApplication.shared.endBackgroundTask(task)
task = .invalid
}
}
Разбор:
beginBackgroundTaskзапрашивает дополнительное время для длинной операции.- В expiration-handler обязательно нужно закрывать задачу через
endBackgroundTask. - После завершения
processLargeFileзадача также закрывается, чтобы не расходовать системный лимит.
Location Updates — отслеживание местоположения в фоновом режиме. Требует явного разрешения пользователя и постоянного отображения индикатора.
func startLocationTracking() {
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
}
Разбор:
- Запрашивается разрешение
requestAlwaysAuthorizationдля фоновой геолокации. allowsBackgroundLocationUpdates = trueвключает обновления в фоне.startUpdatingLocation()запускает фактическое получение координат.
Audio Playback — воспроизведение аудио в фоновом режиме. Приложение продолжает работать, пока воспроизводится звук.
func configureAudioSession() {
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Ошибка настройки аудио сессии")
}
}
Разбор:
AVAudioSession.setCategory(.playback)переводит аудиосессию в режим фонового воспроизведения.setActive(true)активирует сессию перед проигрыванием.do/catchнужен для обработки ошибок конфигурации аудио-стека.
Ограничения фонового режима
Система iOS накладывает строгие ограничения на фоновые операции для экономии ресурсов и продления времени работы от батареи. Приложение получает ограниченное время для завершения операций после перехода в фоновый режим.
func applicationDidEnterBackground(_ application: UIApplication) {
print("Оставшееся время: \(application.backgroundTimeRemaining) секунд")
let task = application.beginBackgroundTask {
print("Фоновое время истекло")
self.endBackgroundTask()
}
performCriticalTasks {
application.endBackgroundTask(task)
}
}
Разбор:
backgroundTimeRemainingпоказывает доступный лимит времени для фоновой работы.- Через
beginBackgroundTaskсоздаётся защищённое окно для критичных операций. - В completion критичной задачи вызывается
endBackgroundTask, чтобы корректно завершить фоновой режим.
Сборка и архивация приложения
Конфигурации сборки
Xcode поддерживает различные конфигурации сборки — Debug, Release, Custom. Каждая конфигурация имеет свои настройки оптимизации, отладки и подписи кода.
// Проверка конфигурации сборки
#if DEBUG
print("Отладочная сборка")
enableDebugFeatures()
#else
print("Релизная сборка")
enableProductionFeatures()
#endif
// Проверка режима оптимизации
#if swift(>=5.5)
print("Swift 5.5 или новее")
#endif
Разбор:
- Условная компиляция
#if DEBUGразделяет поведение для debug и release сборок. - Можно включать отладочные функции только в development-конфигурации.
- Проверка
#if swift(>=5.5)помогает ветвить код по версии компилятора Swift.
Схемы сборки (Schemes)
Схема определяет, как проект собирается, запускается, тестируется и профилируется. Можно создавать пользовательские схемы для разных целей — разработка, тестирование, производство.
Код ITЗагрузка примера кода…
Разбор:
- XML-фрагмент описывает настройки запуска схемы Xcode.
buildConfiguration="Debug"выбирает профиль сборки при запуске.EnvironmentVariablesпозволяет подставлять переменные окружения для разных стендов (API_BASE_URL).
Архивация приложения
Архивация создает дистрибутивную версию приложения для распространения через App Store или тестирования. Процесс включает компиляцию, связывание, кодирование и создание пакета.
# Команда архивации через xcodebuild
xcodebuild archive \
-scheme "MyApplication" \
-configuration "Release" \
-archivePath "build/MyApplication.xcarchive" \
-destination "generic/platform=iOS"
# Экспорт архива
xcodebuild -exportArchive \
-archivePath "build/MyApplication.xcarchive" \
-exportPath "build/export" \
-exportOptionsPlist "ExportOptions.plist"
Разбор:
- Первая команда создаёт архив
.xcarchiveдля выбранной схемы в Release-конфигурации. - Вторая команда экспортирует архив в готовый артефакт (например,
.ipa) по правиламExportOptions.plist. - Такой CLI-пайплайн используется в CI/CD для воспроизводимой сборки.
Распространение приложения
Подготовка к публикации
Перед публикацией в App Store необходимо подготовить метаданные — иконки, скриншоты, описание, ключевые слова, возрастной рейтинг. Все изображения должны соответствовать требованиям размера и формата.
Код ITЗагрузка примера кода…
Разбор:
- JSON описывает набор файлов иконок по устройствам (
idiom), размерам (size) и плотности (scale). - Каждая запись связывает конкретный PNG с требуемым слотом App Icon.
- Блок
infoхранит служебные метаданные каталога ассетов.
Тестирование перед релизом
Перед публикацией необходимо провести полное тестирование — функциональное, производительное, совместимости, безопасности. TestFlight позволяет распространять бета-версии среди тестировщиков.
Код ITЗагрузка примера кода…
Разбор:
Bundle.mainчитает метаданные текущей сборки изInfo.plist.- Ключи
CFBundleShortVersionStringиCFBundleVersionдают версию и номер билда. if #available(iOS 15.0, *)позволяет безопасно включать функции по версии ОС.
Отправка в App Store Connect
Процесс отправки включает загрузку архива, заполнение метаданных, выбор категории, установку цены, указание территорий распространения. После отправки приложение проходит модерацию Apple.
# Загрузка в App Store Connect через xcodebuild
xcodebuild -exportArchive \
-archivePath "build/MyApplication.xcarchive" \
-exportPath "build/export" \
-exportOptionsPlist "AppStoreExportOptions.plist" \
-allowProvisioningUpdates
# Использование Transporter для загрузки
xcrun altool --upload-app \
-f "build/export/MyApplication.ipa" \
-u "developer@apple.com" \
-p "@keychain:Application Loader"
Разбор:
- Блок показывает CLI-этап экспорта и загрузки сборки в App Store Connect.
-allowProvisioningUpdatesразрешает Xcode автоматически подтягивать профили подписи при необходимости.xcrun altool --upload-appотправляет.ipa; учётные данные берутся из keychain-профиля.
Практическая карта жизненного цикла
Жизненный цикл проще держать в голове как рабочую карту "что делать в какой точке", а не как список методов.
Где выполняется основная ответственность
didFinishLaunching— инициализация глобальных сервисов.sceneDidBecomeActive— запуск интерактивных задач и подписок.sceneDidEnterBackground— сохранение изменений и остановка тяжелых операций.viewDidLoad— одноразовая сборка UI и зависимостей экрана.viewWillAppear— актуализация данных перед показом.
Частые ошибки
- Тяжелые запросы или синхронные операции в делегатах приложения.
- Дублирование инициализации одновременно в
viewDidLoadиviewWillAppear. - Отсутствие отмены задач при закрытии экрана или уходе сцены в фон.
Связанные материалы
Практический сценарий одного экрана
Чтобы связать теорию с ежедневной разработкой, удобно держать простой шаблон ответственности по методам.
Где что размещать
viewDidLoad— создание UI, настройка подписок, инъекция сервисов.viewWillAppear— обновление видимых данных и запуск легких операций.viewDidAppear— запуск анимаций и не критичных метрик экрана.viewWillDisappear— остановка таймеров, отмена задач и сохранение черновиков.
Мини-шаблон контроллера
Код ITЗагрузка примера кода…
Разбор:
refreshTaskхранит активную асинхронную загрузку заказов для конкретного экрана.- В
viewWillAppearсоздаётся новаяTask, вviewWillDisappearона отменяется. - Такой шаблон предотвращает "висячие" запросы после ухода пользователя со страницы.
@MainActorуreloadOrders()фиксирует обновление UI на главном потоке.
Такой каркас помогает держать жизненный цикл управляемым и защищает от утечек фоновых задач.
SwiftUI — scenePhase и отмена задач
Код ITЗагрузка примера кода…
Разбор:
@Environment(\.scenePhase)отражает состояние сцены приложения (active / inactive / background).- При
.activeзапускается новаяTaskдля загрузки ленты. - При уходе в фон задача отменяется, чтобы не тратить сеть и не обновлять UI "в пустоту".
onChange(of:scenePhase)— SwiftUI-аналог части логикиAppDelegate/SceneDelegateдля современных приложений.