Active: что это, состояние Active в жизненном цикле iOS

Автор: IT Sectr Опубликовано: 2026-03-03 Время чтения: 10 мин

Active — активное состояние жизненного цикла iOS-приложения, в котором оно находится на переднем плане, получает события касания и взаимодействует с пользователем. Разбираемся, как работает состояние Active, какие методы делегата UIApplicationDelegate за него отвечают и как корректно обрабатывать переходы между Active и Inactive в Swift.

Главное

  • Active — приложение на переднем плане, UIResponder получает touch-события, приложение полностью интерактивно
  • applicationDidBecomeActive — основной метод, сигнализирующий о переходе в Active на iOS
  • ScenePhase.active — эквивалент для SwiftUI, отслеживается через Environment values
  • Возврат из Inactive — после звонка, уведомления или Control Center приложение снова становится Active
  • Ресурсы — в Active приложение имеет наивысший приоритет по памяти и процессору

Active: что это за состояние

Active — состояние жизненного цикла мобильного приложения, в котором оно находится на переднем плане, отображается на экране устройства и активно взаимодействует с пользователем. В этом состоянии приложение получает все события касания, нажатия клавиш, данные с акселерометра и гироскопа, а также имеет полный доступ к графическому процессору для рендеринга интерфейса.

На iOS состояние Active — это часть пятисостоянийной модели жизненного цикла: Not Running → Inactive → Active → Inactive → Background → Suspended → Not Running. На Android аналогом является состояние Activity после вызова onResume, когда Activity находится на вершине стека и принимает пользовательский ввод. Active — единственное состояние, в котором UI полностью интерактивен и реагирует на жесты, скролл, нажатия и анимации.

Система предоставляет приложению в Active максимальный приоритет по процессору и оперативной памяти. Это означает, что система не будет завершать такое приложение при нехватке ресурсов — сначала будут выгружены фоновые и приостановленные процессы. Однако приложение должно эффективно использовать ресурсы, чтобы не разряжать батарею и не вызывать троттлинг CPU.

Для пользователя Active — это нормальное состояние работы с приложением. Пользователь видит интерфейс, может нажимать кнопки, заполнять формы, скроллить ленту. Любое прерывание этого состояния (звонок, уведомление, свайп вверх для Control Center) переводит приложение в Inactive, после чего оно может вернуться в Active или уйти в Background.

Как система определяет, что приложение Active

iOS использует UIApplicationMain для управления состоянием. При переходе в Active система вызывает applicationDidBecomeActive. Для SwiftUI аналогичный механизм — наблюдение за scenePhase через Environment. Android использует onResume как индикатор активности Activity на переднем плане. Оба подхода гарантируют, что приложение получает уведомление о смене состояния и может адаптировать своё поведение.

ПлатформаМетод/событиеSwift (UIKit)SwiftUIAndroid (Kotlin)
iOSПереход в ActiveapplicationDidBecomeActivescenePhase == .active
iOSУход из ActiveapplicationWillResignActivescenePhase == .inactive
AndroidПереход в ActiveonResume()
AndroidУход из ActiveonPause()

Active в iOS: Swift, UIKit и SwiftUI

В iOS состояние Active обрабатывается через UIApplicationDelegate. Основной метод — applicationDidBecomeActive(_:). Он вызывается при первом запуске приложения и при возврате из Inactive. Этот метод — идеальное место для возобновления задач, которые были приостановлены при уходе в Inactive: запуск анимаций, возобновление таймеров, перезапуск датчиков, проверка обновлений данных на сервере.

UIKit: AppDelegate и SceneDelegate

С iOS 13 Apple представила UISceneDelegate для поддержки нескольких окон на iPad. В этом случае applicationDidBecomeActive заменяется на sceneDidBecomeActive для каждого отдельного сцены. Приложения, поддерживающие только один экран, могут продолжать использовать UIApplicationDelegate. Оба подхода вызываются в момент, когда приложение или сцена становится активной.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // Приложение стало активным — возобновляем задачи
    func applicationDidBecomeActive(_ application: UIApplication) {
        resumeAnimations()
        restartTimers()
        refreshDataIfNeeded()
        startObservingSensors()
    }

    // Приложение теряет активность — приостанавливаем
    func applicationWillResignActive(_ application: UIApplication) {
        pauseAnimations()
        stopTimers()
        saveDraftData()
    }

    private func resumeAnimations() {
        UIView.animate(withDuration: 0.3) {
            // Возобновление UI-анимаций
        }
    }

    private func refreshDataIfNeeded() {
        let lastRefresh = UserDefaults.standard.object(forKey: "lastRefresh") as? Date ?? .distantPast
        if Date().timeIntervalSince(lastRefresh) > 300 {
            fetchDataFromServer()
        }
    }
}

В коде показана корректная обработка Active в UIKit. applicationDidBecomeActive возобновляет анимации, таймеры и проверяет, требуется ли обновление данных. applicationWillResignActive приостанавливает всё, что может потреблять ресурсы, и сохраняет черновики. Такая пара методов гарантирует, что приложение правильно реагирует на смену состояния.

SwiftUI: scenePhase

В SwiftUI нет AppDelegate — управление состоянием происходит через Environment<ScenePhase>. Значение .active устанавливается, когда сцена находится на переднем плане и интерактивна. SwiftUI автоматически перезапускает анимации и обновления при возврате в Active. Разработчику нужно только подписаться на onChange для выполнения побочных эффектов.

swift
import SwiftUI

@main
struct ActiveDemoApp: App {
    @Environment(\.scenePhase) private var scenePhase

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of: scenePhase) { oldPhase, newPhase in
            switch newPhase {
            case .active:
                print("Сцена стала активной")
                resumeWork()
            case .inactive:
                print("Сцена стала неактивной")
                pauseWork()
            case .background:
                print("Сцена ушла в фон")
                saveState()
            @unknown default:
                break
            }
        }
    }

    private func resumeWork() {
        // Возобновление Network-запросов, анимаций
    }

    private func pauseWork() {
        // Приостановка чувствительных ко времени задач
    }

    private func saveState() {
        // Сохранение состояния приложения
    }
}

В SwiftUI scenePhase — это единственный источник истины о состоянии приложения. onChange позволяет выполнять действия при каждом переходе. Важно помнить, что scenePhase доступна только на iOS 14+ и в SwiftUI Lifecycle. Для приложений на UIKit со SwiftUI-экранми используйте подход с UIApplicationDelegate.

Переходы в состояние Active

Active достигается несколькими путями. Первый и очевидный — холодный старт: пользователь нажимает на иконку, приложение переходит из Not Running через Inactive в Active. Второй — возврат из фона: пользователь переключается обратно в приложение через App Switcher, приложение проходит через Inactive и становится Active. Третий — возврат из временного прерывания: пользователь завершает звонок, закрывает Control Center или отвечает на уведомление — приложение возвращается из Inactive в Active.

Цепочка переходов в Active

Not Running → Inactive → Active — холодный старт. Background → Inactive → Active — возврат из фона. Inactive → Active — возврат из временного прерывания. В каждом случае applicationDidBecomeActive вызывается, но контекст может отличаться. При холодном старте перед Active вызывается didFinishLaunchingWithOptions, при возврате из фона — willEnterForeground. Разработчик может использовать эти различия для выбора стратегии восстановления состояния.

СценарийПуть переходаКоллбэки iOSКоллбэки Android
Холодный стартNot Running → ActivedidFinishLaunching → didBecomeActiveonCreate → onStart → onResume
Возврат из фонаBackground → ActivewillEnterForeground → didBecomeActiveonRestart → onStart → onResume
Возврат из SuspendedSuspended → ActivewillEnterForeground → didBecomeActiveonRestart → onStart → onResume
После прерыванияInactive → ActivedidBecomeActiveonResume

Важное замечание: при возврате из Suspended iOS не вызывает didFinishLaunchingWithOptions, так как приложение уже было загружено в память. Это означает, что код инициализации, размещённый в этом методе, не выполняется повторно. Разработчики часто забывают об этом и переносят критическую логику в applicationWillEnterForeground или applicationDidBecomeActive для обоих сценариев.

Active в Android: жизненный цикл Activity

В Android аналогом Active является состояние Activity после вызова onResume(). Activity считается активной, когда она находится на переднем плане и принимает пользовательский ввод. Это состояние соответствует вершине Activity-стека. Если другое Activity появляется поверх (даже частично), текущее Activity переходит в состояние onPause — аналог iOS Inactive.

Ключевое отличие Android — несколько Activity могут быть активными одновременно в multi-window режиме (split screen, freeform). В этом случае Activity, с которым взаимодействует пользователь, считается активным, а соседнее — приостановленным (onPause). iOS не поддерживает multi-window на iPhone, только на iPad через UIScene.

kotlin
class MainActivity : AppCompatActivity() {

    override fun onResume() {
        super.onResume()
        // Приложение стало активным — возобновляем задачи
        resumeCameraPreview()
        startLocationUpdates()
        activateSensors()
    }

    override fun onPause() {
        super.onPause()
        // Приложение теряет активность — освобождаем ресурсы
        releaseCamera()
        stopLocationUpdates()
        deactivateSensors()
    }

    private fun resumeCameraPreview() {
        // Запуск предпросмотра камеры (требует разрешения)
        cameraProvider?.unbindAll()
        cameraProvider?.bindToLifecycle(
            this,
            cameraSelector,
            preview,
            imageAnalyzer
        )
    }

    private fun startLocationUpdates() {
        val locationRequest = LocationRequest.Builder(
            Priority.PRIORITY_HIGH_ACCURACY, 5000
        ).build()
        locationClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.getMainLooper()
        )
    }
}

В коде показана обработка Active в Android через onResume/onPause. onResume возобновляет работу с камерой, геолокацией и датчиками — ресурсы, которые должны быть активны только когда приложение видимо пользователю. onPause освобождает эти ресурсы, чтобы не расходовать батарею. CameraX lifecycle-aware API автоматически приостанавливает предпросмотр при onPause.

Лучшие практики обработки Active

Первое правило — не выполняйте тяжёлые операции в applicationDidBecomeActive или onResume. Загрузка данных, парсинг JSON, работа с базой данных — всё это должно быть асинхронным и не блокировать главный поток. Используйте GCD (DispatchQueue) в iOS и Coroutines в Kotlin для фоновых задач. Главный поток должен только обновлять UI и запускать асинхронные операции.

Второе правило — синхронизируйте состояние при каждом возврате в Active. Пользователь мог изменить настройки в системном приложении, получить push-уведомление или обновить данные в другом приложении. Проверяйте актуальность кеша при переходе в Active — возможно, данные устарели за время отсутствия пользователя.

Третье правило — не полагайтесь на Active как на единственное состояние. Приложение может пропустить Active и перейти напрямую из Not Running в Background (если запущено в фоновом режиме). На iOS это происходит при запуске через push-уведомление с опцией content-available. На Android — при запуске через BroadcastReceiver. Всегда проверяйте текущее состояние перед выполнением UI-операций.

Четвёртое правило — используйте Activity Result API на Android вместо onActivityResult. Это позволяет обрабатывать результат вызова камеры, галереи или разрешений прямо в Active-состоянии без потери данных при пересоздании Activity. Для iOS используйте async/await с UIApplication.shared.open для системных диалогов.

swift
import UIKit

final class ActiveStateManager {
    static let shared = ActiveStateManager()
    private var isActive = false

    func setActive(_ active: Bool) {
        isActive = active
        if active {
            NotificationCenter.default.post(name: .appDidBecomeActive, object: nil)
        }
    }

    func performWhenActive(_ block: @escaping () -> Void) {
        if isActive {
            block()
        } else {
            // Отложить выполнение до возврата в Active
            NotificationCenter.default.addObserver(
                forName: .appDidBecomeActive,
                object: nil,
                queue: .main
            ) { _ in
                block()
            }
        }
    }
}

extension Notification.Name {
    static let appDidBecomeActive = Notification.Name("appDidBecomeActive")
}

В коде показан менеджер состояния Active, который позволяет другим компонентам приложения проверять текущее активное состояние. performWhenActive либо выполняет блок немедленно, если приложение активно, либо откладывает выполнение до возврата в Active. Это полезно для сервисов, которые должны выполнить действие после того, как пользователь вернётся в приложение.

Часто задаваемые вопросы

Как часто вызывается applicationDidBecomeActive?

Метод вызывается каждый раз, когда приложение переходит в активное состояние: при первом запуске, при возврате из фона, после закрытия Control Center или Notification Center, после завершения звонка. В нормальной сессии может быть вызван 5–10 раз в зависимости от действий пользователя. Не размещайте в этом методе одноразовую инициализацию.

Чем отличается Active от Visible на iOS?

Visible — неофициальный термин, означающий, что приложение видимо на экране, но может не принимать события (например, частично перекрыто другим окном на iPad). Active — официальное состояние, в котором приложение и видимо, и интерактивно. На iPhone Visible приложение всегда Active, на iPad возможна ситуация Visible + Inactive.

Что такое didBecomeActive vs willEnterForeground?

willEnterForeground вызывается при возврате из фона, но приложение ещё не активно — оно находится в Inactive. didBecomeActive вызывается после того, как приложение стало полностью интерактивным. Если нужно выполнить действие до того, как пользователь увидит интерфейс — используйте willEnterForeground. Если после отображения — didBecomeActive.

Может ли приложение быть Active без видимого UI?

Нет. Active подразумевает, что приложение находится на переднем плане и отображается на экране. Без видимого UI приложение может быть в Background или Suspended. Исключение — iPad multi-window, где одно окно может быть активным, а другое — нет, но оба видимы. VoiceOver и диктофон не меняют это правило.

Как протестировать переход в Active на симуляторе?

На iOS симуляторе нажмите Cmd+Shift+H для перехода на Home Screen (приложение уходит в Background), затем снова нажмите на иконку приложения. Используйте Cmd+L для блокировки экрана (willResignActive) и разблокировки (didBecomeActive). Для тестирования Inactive вызовите Control Center (Cmd+Shift+; для macOS-клавиатуры) или Notification Center.

Итоги

  • Active — состояние приложения на переднем плане с полным доступом к пользовательскому вводу и максимальным приоритетом ресурсов
  • iOS UIKit — applicationDidBecomeActive для возобновления анимаций, таймеров и датчиков
  • SwiftUI — scenePhase .active через Environment, onChange для побочных эффектов
  • Android — onResume/onPause как аналог Active/Inactive, с поддержкой multi-window
  • Переходы — Active достигается из Not Running (холодный старт), Background и Inactive
  • Ресурсы — тяжёлые операции в didBecomeActive должны быть асинхронными, не блокировать главный поток
  • Синхронизация — проверка актуальности кеша и данных при каждом возврате в Active

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также