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

Как создать Background Task?

2.0 Middle🔥 192 комментариев
#Многопоточность и асинхронность

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

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

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

Создание Background Tasks в iOS

Background Tasks — это механизм в iOS для выполнения задач в фоновом режиме с ограничениями по времени и ресурсам. Фреймворк BackgroundTasks (доступен с iOS 13+) предоставляет контролируемый способ выполнения фоновой работы, заменяя устаревшие API.

Основные типы Background Tasks

  1. BGAppRefreshTask — для периодического обновления контента приложения
  2. BGProcessingTask — для длительных операций (очистка кэша, индексация и т.д.)
  3. BGProcessingTaskRequest с requiresExternalPower — для энергоемких задач при подключении к питанию

Шаги реализации

1. Добавление Capabilities

В Xcode добавьте Background Modes в Signing & Capabilities:

  • ✅ Background fetch
  • ✅ Background processing

2. Регистрация идентификаторов задач

import BackgroundTasks

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, 
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Регистрация обработчиков
        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.yourapp.refresh", 
                                        using: nil) { task in
            self.handleAppRefresh(task: task as! BGAppRefreshTask)
        }
        
        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.yourapp.processing", 
                                        using: nil) { task in
            self.handleProcessingTask(task: task as! BGProcessingTask)
        }
        
        return true
    }
}

3. Планирование задач

func scheduleAppRefresh() {
    let request = BGAppRefreshTaskRequest(identifier: "com.yourapp.refresh")
    
    // Запуск не ранее чем через 15 минут
    request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
    
    do {
        try BGTaskScheduler.shared.submit(request)
        print("✅ App Refresh запланирован")
    } catch {
        print("❌ Ошибка планирования: \(error.localizedDescription)")
    }
}

func scheduleProcessingTask() {
    let request = BGProcessingTaskRequest(identifier: "com.yourapp.processing")
    
    // Для задач, требующих подключения к сети
    request.requiresNetworkConnectivity = true
    
    // Для энергоемких задач
    request.requiresExternalPower = false
    
    do {
        try BGTaskScheduler.shared.submit(request)
    } catch {
        print("Ошибка: \(error)")
    }
}

4. Реализация обработчиков задач

func handleAppRefresh(task: BGAppRefreshTask) {
    // Важно: запланировать следующую задачу ДО выполнения текущей
    scheduleAppRefresh()
    
    // Создаем операционную очередь для выполнения работы
    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 1
    
    // Добавляем операцию
    queue.addOperation {
        // Выполняем фоновую работу
        self.fetchNewData()
        
        // После завершения помечаем задачу как выполненную
        task.setTaskCompleted(success: true)
    }
    
    // Обработчик истечения времени
    task.expirationHandler = {
        queue.cancelAllOperations()
        task.setTaskCompleted(success: false)
    }
}

func handleProcessingTask(task: BGProcessingTask) {
    let queue = OperationQueue()
    
    task.expirationHandler = {
        queue.cancelAllOperations()
    }
    
    queue.addOperation {
        // Выполняем длительную операцию
        self.performDatabaseCleanup()
        self.updateSearchIndex()
        
        task.setTaskCompleted(success: true)
    }
}

5. Управление жизненным циклом задачи

Критически важные аспекты:

  • Всегда вызывайте setTaskCompleted(success:) — система контролирует ресурсы
  • Обрабатывайте expirationHandler — у вас есть около 30 секунд на завершение
  • Не превышайте лимиты — обработка прерывается по истечении времени

Лучшие практики

Оптимизация производительности:

func fetchNewData() {
    // Используйте фоновые сессии URLSession
    let config = URLSessionConfiguration.background(withIdentifier: "backgroundFetch")
    config.isDiscretionary = true // Система оптимизирует время выполнения
    config.timeoutIntervalForResource = 1800 // 30 минут максимум
    
    let session = URLSession(configuration: config)
    // ... выполнение запроса
}

Мониторинг состояния:

func checkPendingTasks() {
    BGTaskScheduler.shared.getPendingTaskRequests { requests in
        for request in requests {
            print("Ожидающая задача: \(request.identifier)")
        }
    }
}

Ограничения и рекомендации

  • Время выполнения — обычно 30 секунд, но может варьироваться
  • Частота запуска — система оптимизирует исходя из использования приложения
  • Приоритизация — задачи выполняются при оптимальных условиях (зарядка, Wi-Fi)
  • Тестирование — используйте e -launch -arg1 -arg2 в терминале или симулятор

Отладка

// Включение логов для отладки
BGTaskScheduler.shared.register(forTaskWithIdentifier: "debug.task", using: .main) { task in
    print("⌛️ Время до истечения: \(task.expirationHandler != nil ? "установлено" : "не установлено")")
    // ... выполнение задачи
}

Альтернативные подходы

Для специфических случаев также доступны:

  • Background URLSession — для загрузки/выгрузки данных
  • Push-уведомления с content-available — для мгновенного обновления
  • Location updates — для задач, связанных с геолокацией

Важно: Background Tasks не гарантируют немедленного выполнения. Система iOS оптимизирует запуск задач для сохранения батареи, основываясь на пользовательских привычках и условиях устройства. Всегда проектируйте фоновые задачи как идемпотентные операции, которые могут быть безопасно прерваны и перезапущены.

Правильная реализация Background Tasks существенно улучшает пользовательский опыт, позволяя приложению оставаться актуальным без постоянной работы в foreground.