Как продолжать «считать таймер» когда пользователь скрыл приложение или открыл что-то другое?

В Swift, существует несколько способов продолжать отсчет времени таймера, даже когда пользователь сворачивает приложение или открывает другое.

Первый способ - использовать Background Modes. Вам нужно включить Background Modes в настройках вашего проекта и выбрать опцию "Background fetch". После этого вам нужно добавить поддержку этого режима в ваш код.

В AppDelegate вам нужно добавить метод application(_:performFetchWithCompletionHandler:). Этот метод будет вызываться системой периодически для фонового выполнения операций, и вы можете использовать его для обновления таймера. При вызове этого метода, вы можете обновить значение таймера и обновить интерфейс, если это необходимо.

Код мог выглядеть следующим образом:

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // Обновляем таймер и интерфейс
    updateTimer()
    
    completionHandler(.newData)
}

Теперь ваше приложение будет запускаться в фоновом режиме и обновлять таймер.

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

Вы можете использовать UNUserNotificationCenter для создания локального уведомления. Пример кода:

import UserNotifications

// Регистрируем уведомления
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { success, error in
    if success {
        // Уведомления разрешены
    } else if let error = error {
        // Произошла ошибка при запросе разрешений
    }
}

// Создаем и планируем уведомление
let content = UNMutableNotificationContent()
content.title = "Время истекло"
content.body = "Вернитесь в приложение, чтобы продолжить отсчет времени."
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: false)
let request = UNNotificationRequest(identifier: "timerExpired", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
    if let error = error {
        // Произошла ошибка при создании уведомления
    }
}

Третий способ - использовать фоновую обработку. Если ваше приложение выполняет фоновую обработку, то вы можете использовать этот механизм для продолжения отсчета времени. Вы можете настроить фоновую обработку в вашем проекте и добавить код, который будет выполняться при фоновой обработке. В этом коде, вы можете обновить таймер и интерфейс.

func applicationDidEnterBackground(_ application: UIApplication) {
    // Выполняем фоновую обработку
    updateTimer()
}

Обратите внимание, что фоновая обработка имеет ограничения по времени выполнения и может быть прервана системой, если ваше приложение не активно достаточно долго.

Независимо от того, какой способ вы выберете, важно помнить о ограничениях системы на выполнение фоновых операций.