← Назад к вопросам

Как получаем уведомления о смене состояния с active на inactive?

1.3 Junior🔥 251 комментариев
#UIKit и верстка

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Мониторинг изменения состояния приложения с active на inactive

Для отслеживания изменения состояния приложения с active на inactive в iOS существуют несколько подходов, которые можно разделить на два основных типа: через уведомления NotificationCenter и через методы жизненного цикла AppDelegate/SceneDelegate.

Основные подходы

1. Через NotificationCenter (универсальный способ)

Система генерирует уведомления при изменении состояния приложения, которые можно наблюдать из любой части кода:

import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Наблюдение за переходом в неактивное состояние
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(appWillResignActive),
            name: UIApplication.willResignActiveNotification,
            object: nil
        )
        
        // Наблюдение за возвратом в активное состояние
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(appDidBecomeActive),
            name: UIApplication.didBecomeActiveNotification,
            object: nil
        )
    }
    
    @objc func appWillResignActive(_ notification: Notification) {
        // Вызывается при переходе из active в inactive
        // Например: при входящем звонке, переходе в multitask view, открытии Control Center
        print("Приложение переходит в состояние inactive")
        saveCurrentState()
        pauseGameIfNeeded()
    }
    
    @objc func appDidBecomeActive(_ notification: Notification) {
        // Вызывается при возврате в активное состояние
        print("Приложение снова активно")
        resumeGameIfNeeded()
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

2. Через AppDelegate (для UIKit без сцен)

В старом подходе с использованием только AppDelegate:

import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func applicationWillResignActive(_ application: UIApplication) {
        // Вызывается при переходе из active в inactive
        // Происходит при прерываниях (звонок, SMS) или при выходе пользователя из приложения
        print("applicationWillResignActive вызван")
        
        // Обычные действия:
        // - Приостановка таймеров
        // - Пауза игр или видео
        // - Сохранение состояния UI
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        // Вызывается при возврате в активное состояние
        print("applicationDidBecomeActive вызван")
        
        // Возобновление прерванных задач
    }
}

3. Через SceneDelegate (для приложений с поддержкой сцен)

Для приложений, использующих многозадачность и несколько окон:

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
    func sceneWillResignActive(_ scene: UIScene) {
        // Вызывается при переходе сцены из active в inactive
        // Важно: может вызываться для отдельных сцен в многозадачном режиме
        print("Сцена переходит в состояние inactive")
        
        // Сохраняем данные, специфичные для этой сцены
        // Приостанавливаем тяжелые операции
    }
    
    func sceneDidBecomeActive(_ scene: UIScene) {
        // Вызывается при активации сцены
        print("Сцена стала активной")
        
        // Восстанавливаем состояние для конкретной сцены
    }
}

Ключевые различия и нюансы

Разница между состояниями:

  • ActiveInactive: временное состояние, когда приложение все еще работает на переднем плане, но не получает события (например, во время входящего звонка)
  • InactiveBackground: приложение полностью уходит с переднего плана

Важные моменты при обработке:

  1. Скорость выполнения: Методы перехода в inactive должны выполняться быстро (примерно 5 секунд), иначе система может завершить приложение
  2. Освобождение ресурсов: Рекомендуется освобождать ресурсы, которые не нужны в неактивном состоянии
  3. Сохранение состояния: Критически важные данные пользователя должны сохраняться
  4. Приостановка операций: Сетевые запросы, таймеры, анимации должны быть приостановлены

Практический пример комбинированного подхода

class StateManager {
    static let shared = StateManager()
    private init() {}
    
    private var isAppActive = true
    
    func setupObservers() {
        // Для iOS 13+ с поддержкой сцен
        if #available(iOS 13.0, *) {
            NotificationCenter.default.addObserver(
                self,
                selector: #selector(handleSceneWillResignActive),
                name: UIScene.willDeactivateNotification,
                object: nil
            )
        } else {
            // Для более старых версий iOS
            NotificationCenter.default.addObserver(
                self,
                selector: #selector(handleAppWillResignActive),
                name: UIApplication.willResignActiveNotification,
                object: nil
            )
        }
    }
    
    @objc private func handleSceneWillResignActive() {
        print("Сцена деактивируется")
        handleTransitionToInactive()
    }
    
    @objc private func handleAppWillResignActive() {
        print("Приложение деактивируется")
        handleTransitionToInactive()
    }
    
    private func handleTransitionToInactive() {
        isAppActive = false
        
        // 1. Сохраняем пользовательские данные
        UserDefaults.standard.synchronize()
        
        // 2. Приостанавливаем воспроизведение медиа
        AudioManager.shared.pause()
        
        // 3. Останавливаем таймеры
        TimerManager.shared.suspendAllTimers()
        
        // 4. Сохраняем состояние UI
        saveUIState()
        
        // 5. Отправляем аналитику
        Analytics.track(event: .appWentToInactive)
    }
}

Рекомендации по использованию

  • Используйте NotificationCenter для компонентов, которые должны реагировать на изменение состояния из любого места приложения
  • Используйте AppDelegate/SceneDelegate для глобальных действий, затрагивающих все приложение
  • Всегда удаляйте наблюдателей в deinit или при уничтожении объекта
  • Тестируйте различные сценарии: входящие звонки, уведомления, переход в многозадачность
  • Учитывайте многозадачность: в iOS 13+ разные сцены могут находиться в разных состояниях

Выбор конкретного подхода зависит от архитектуры приложения, целевой версии iOS и конкретных требований к обработке изменения состояния.

Как получаем уведомления о смене состояния с active на inactive? | PrepBro