BGTaskScheduler — е рамка на Apple за планиране и изпълнение на фонови задачи в приложения за iOS 13 и по-нови. Тя замени остарелите Background Fetch и performFetch, предоставяйки единен API за работа с фонови операции. Според Apple Developer Documentation, 2026, рамката включва два типа задачи: BGProcessingTask за дълги операции и BGAppRefreshTask за кратки актуализации на съдържание.
Основни точки
BGTaskScheduler — е системна рамка на Apple, представена в iOS 13, която централизирано управлява изпълнението на фонови задачи. Преди нейното появяване разработчиците използваха UIApplication backgroundTasks, performFetch и обработка на събития в appDelegate, което водеше до фрагментация на кода и непредвидимо поведение.
Рамката работи на принципа на отложено планиране: приложението регистрира задачи с уникални идентификатори, а iOS сама определя оптималния момент за тяхното изпълнение. Системата взема предвид нивото на батерията, активността на потребителя, състоянието на мрежата и други фактори.
Основни възможности включват работа както с кратки, така и с дълги фонови операции. За разлика от AlarmManager в Android, BGTaskScheduler не гарантира точно време за изпълнение — системата си запазва правото да отложи задачата, ако условията са неблагоприятни.
BGTaskScheduler използва архитектура, базирана на манипулатори (handlers). Приложението регистрира манипулатор за всеки тип задача и системата го извиква, когато настъпи подходящият момент. Самата рамка не изпълнява задачата директно — тя само уведомява приложението, че е време да я стартира.
Регистрацията започва с деклариране на идентификатора на задачата в Info.plist чрез масива BGTaskSchedulerPermittedIdentifiers. След това в кода на приложението се извиква методът registerHandler(forTaskWithIdentifier:) с манипулатор-затваряне.
import BackgroundTasks
let taskID = "com.example.app.refresh"
BGTaskScheduler.shared.registerHandler(
forTaskWithIdentifier: taskID,
using: DispatchQueue.global()
) { task in
task.expirationHandler = {
// извиква се при принудително прекратяване
}
processBackgroundTask(task as! BGAppRefreshTask)
}
След регистрация приложението трябва изрично да поиска изпълнение на задачата чрез submitTaskRequest. Заявката съдържа идентификатора на задачата и датата на най-ранното възможно стартиране. Системата запазва заявката и я обработва, когато прецени, че условията са подходящи.
let request = BGAppRefreshTaskRequest(
identifier: taskID
)
request.earliestBeginDate = Date(timeIntervalSinceNow: 3600)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Грешка при планиране: \(error)")
}
BGTaskScheduler предоставя два основни типа задачи, всеки от които е предназначен за свой сценарий на използване. Изборът на правилния тип пряко влияе върху вероятността за успешно изпълнение на задачата от системата.
BGAppRefreshTask е предназначена за кратки фонови актуализации на съдържание: зареждане на нови данни, синхронизация със сървъра, актуализиране на уиджети. Времето за изпълнение е ограничено до 30 секунди, след което системата принудително прекратява задачата. Този тип задачи се изпълняват по-често от BGProcessingTask и имат по-висок приоритет.
BGProcessingTask е предназначена за по-дълги операции: обработка на медийни файлове, индексиране на данни от Core Data, създаване на резервни копия. Задачата може да продължи до няколко минути, но системата я стартира по-рядко и само при благоприятни условия — свързване към захранване, стабилен Wi-Fi и ниско натоварване на устройството.
| Параметър | BGAppRefreshTask | BGProcessingTask |
|---|---|---|
| Времеви лимит | 30 секунди | няколко минути |
| Честота на стартиране | висока | ниска |
| Условия | всякакви | захранване + Wi-Fi |
| Изисква захранване | не | препоръчително |
| Пример | актуализиране на поток | обработка на видео |
Правилната регистрация — е задължително условие за работата на BGTaskScheduler. Ако задачата не е регистрирана в Info.plist, системата ще игнорира всяка заявка за нейното изпълнение.
Към файла Info.plist се добавя масив BGTaskSchedulerPermittedIdentifiers със списък от текстови идентификатори. Всеки идентификатор трябва да бъде уникален в рамките на приложението. Apple препоръчва използването на обратна домейн нотация.
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.example.app.refresh</string>
<string>com.example.app.processing</string>
</array>
За планиране се използва методът submitTaskRequest. Ако задачата вече не е необходима, може да бъде отменена чрез cancelTaskRequest или cancelAllTaskRequests. Системата автоматично отменя задачите при изтриване на приложението или нулиране на данните.
BGTaskScheduler предоставя възможност за проследяване на състоянието на планираните задачи чрез getPendingTaskRequests. Този метод връща списък на всички активни заявки с информация за техния тип, идентификатор и earliestBeginDate. За всяка заявка може да се провери дали вече е изпълнена или отказана и да се вземе решение за повторно планиране.
Важно е да се отбележи, че системата не предоставя директно обратно извикване за успеха на фоновата задача — манипулаторът сам трябва да докладва резултата чрез свойствата на задачата. setTaskCompleted позволява маркиране на задачата като успешно завършена, след което системата може да стартира следващата планирана задача от този тип. Ако задачата не е извикала setTaskCompleted, системата я счита за завършена след изтичане на времето или при принудително прекратяване.
За диагностика на проблеми се препоръчва използването на OSLog в манипулатора и преглед на логовете чрез Console.app на Mac. Apple също така предоставя инструмента MetricKit за анализ на производителността на фонови задачи — той събира данни за времето за изпълнение, консумацията на енергия и честотата на стартиране, които могат да се използват за оптимизация.
// Отмяна на конкретна задача
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: taskID)
// Отмяна на всички задачи
BGTaskScheduler.shared.cancelAllTaskRequests()
// Проверка на планираните задачи
BGTaskScheduler.shared.getPendingTaskRequests { requests in
print("Планирани \(requests.count) задачи")
}
BGTaskScheduler налага строги ограничения върху фоновата работа. Системата може да отложи задачата за неопределен период, ако условията са неблагоприятни. Разработчикът трябва да разбере, че рамката не е предназначена за задачи в реално време.
Сред ключовите ограничения: системата не гарантира изпълнение на задачата в определеното време, максималният брой едновременни задачи е ограничен, а консумацията на енергия се контролира строго. Стартирането на няколко задачи последователно може да доведе до тяхното сливане или отмяна.
За увеличаване на вероятността за изпълнение се препоръчва задаване на earliestBeginDate не по-рано от 1 час за BGProcessingTask и 15 минути за BGAppRefreshTask. Също така е важно да се обработва expirationHandler — ако задачата не се вмества в лимита, системата извиква този манипулатор за коректно прекратяване. Повторното планиране трябва да се извършва вътре в самия манипулатор, за да се поддържа непрекъснат цикъл на фонова работа.
Друго важно ограничение се отнася до мрежовите заявки. BGTaskScheduler не гарантира наличие на активна мрежова връзка по време на изпълнение на задачата. Приложението трябва самостоятелно да проверява наличността на мрежата чрез NWPathMonitor и да отлага обработката, ако връзката отсъства. Това се различава от Android JobScheduler, който може да активира задачата само при свързване към мрежа от определен тип. На практика разработчиците често комбинират BGTaskScheduler с фонови URL сесии на NSURLSession за надеждно зареждане на данни.
От macOS Catalina нататък BGTaskScheduler е достъпен и на Mac. Това позволява създаването на междуплатформени фонови задачи за UIKit приложения, работещи на Apple Silicon. На watchOS рамката работи ограничено — достъпни са само кратки BGAppRefreshTask за актуализиране на усложнения и синхронизация на данни с iPhone. Разработчиците трябва да вземат предвид платформените разлики при планиране на фоновата архитектура.
За отстраняване на грешки в BGTaskScheduler Apple предоставя няколко инструмента. Командата e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.example.task"] в lldb принудително стартира фоновата задача, игнорирайки системните ограничения. В Xcode е наличен флагът Simulate Background Fetch в менюто Debug, който емулира кратка фонова актуализация. За анализ на производителността се използва MetricKit — той събира информация за честотата на стартиране, продължителността на изпълнение и консумацията на енергия на всяка задача. Тези данни помагат за оптимизиране на честотата на планиране и избор на правилния тип задача.
На практика BGTaskScheduler е подходящ за актуализиране на данни на уиджети, синхронизация на iCloud, обработка на push известия със съдържание и индексиране на търсене в Spotlight. Не е подходящ за изпращане на аналитика в реално време, чат приложения или задачи, изискващи незабавно изпълнение.
За задълбочено изучаване на BGTaskScheduler Apple препоръчва официалната документация на WWDC: сесията „Advances in Background Tasks” (2020) покрива миграцията от остарели API, а „Background Tasks in Practice” (2021) съдържа реални случаи на използване. Също така е полезна секцията Energy Efficiency Guide, където е описано как рамката се вписва в общата стратегия за пестене на енергия на Apple. Примери за код са достъпни в официалното хранилище на Apple Developer в GitHub с пълни проекти за iOS и macOS.
Често задавани въпроси
Background Fetch беше ограничен до една фонова задача на приложение и нямаше механизъм за приоритети. BGTaskScheduler поддържа множество задачи с различни типове, предоставя единен API и автоматично управление на енергията.
Apple не поставя изрично ограничение на броя регистрирани идентификатори, но на практика се препоръчва използването на не повече от 5–10 задачи. По-големият брой намалява вероятността за изпълнение на всяка конкретна задача поради конкуренция за системни ресурси.
За отстраняване на грешки използвайте командата e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.example.task"] в lldb. Тя принудително стартира задачата, заобикаляйки системните ограничения. Също така е наличен флагът Xcode Simulate Background Fetch в менюто Debug.
Да, BGTaskScheduler може да стартира процес дори ако приложението е принудително затворено от потребителя. Въпреки това системата може да приложи допълнителни закъснения и не всички типове задачи гарантират стартиране в този сценарий.
Системата ще извика expirationHandler, предавайки на задачата сигнал за необходимост от прекратяване. Ако приложението игнорира този сигнал и продължи да работи, iOS принудително прекратява процеса. След това системата може да намали приоритета на всички фонови задачи на приложението.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също