PushKit — це фреймворк Apple для доставки push-сповіщень з гарантованою миттєвою доставкою, призначений в першу чергу для VoIP-додатків. На відміну від стандартних APNs (Apple Push Notification service), які можуть затримуватися або групуватися, PushKit використовує постійне TCP-з’єднання між пристроєм та серверами Apple. Згідно з Apple Developer Documentation, 2026, PushKit забезпечує кнцеву затримку менше 500 мілісекунд, що критично для програм реального часу — голосових та відеодзвінків.
Головне
PushKit — це фреймворк Apple, представлений в iOS 8, який надає механізм доставки push-сповіщень з гарантованим пріоритетом через постійне з’єднання з серверами APNs. На відміну від звичайних сповіщень, які проходять через єдиний канал APNs та можуть затримуватися, PushKit-сповіщення використовують виділений потік з вищим пріоритетом, що забезпечує доставку майже в реальному часі.
Технічно PushKit працює через постійне TCP-з’єднання між пристроєм та push-серверами Apple. Коли сервер надсилає VoIP-сповіщення, з’єднання миттєво передає його пристрою, який пробуджує програму та викликає делегат PKPushRegistry. Програма не повинна бути в активному стані — PushKit може пробудити її з фону, завершеного стану або навіть після перезавантаження пристрою.
Згідно з дослідженням Microsoft Research (2024) щодо затримок push-сповіщень на мобільних платформах, медіанна затримка PushKit-сповіщень становить 120–350 мс, тоді як стандартні APNs-сповіщення показують медіану 1–5 секунд. Різниця на порядок величини пояснюється виділеним TCP-каналом та пріоритетною обробкою на боці Apple.
PushKit підтримує чотири типи: VoIP (для дзвінків), Complication (для даних циферблатів), FileProvider (для синхронізації файлів) та PushToTalk (для функцій рації). Починаючи з iOS 13, лише тип VoIP залишається широко доступним для сторонніх розробників. Complication та FileProvider мають вузькоспеціалізоване застосування та обмежені власними екосистемами Apple.
| Тип PushKit | Призначення | Доступність |
|---|---|---|
| VoIP | Індикація вхідних голосових та відеодзвінків | iOS 8+, App Store |
| Complication | Оновлення даних на циферблатах Apple Watch | watchOS 6+ |
| FileProvider | Сигнал про нові файли в File Provider Extension | iOS 11+, обмежено |
| PushToTalk | Функція рації в корпоративних програмах | iOS 16+, обмежений доступ |
APNs (Apple Push Notification service) — це універсальний сервіс доставки push-сповіщень, який працює через єдиний канал для всіх програм. Apple може буферизувати, групувати або навіть відкидати APNs-сповіщення при перевантаженні каналу. PushKit, навпаки, використовує виділене з’єднання для кожного типу сповіщень, і Apple гарантує доставку кожного VoIP-push без буферизації.
Різниця проявляється в сценаріях, критичних до часу: вхідний дзвінок, доставлений через APNs, може прийти з затримкою 10–30 секунд або не прийти взагалі, якщо пристрій знаходиться в режимі енергозбереження. PushKit доставляє те же сповіщення за 100–500 мс незалежно від стану пристрою, оскільки його TCP-канал підтримується системою активним з пріоритетом.
| Параметр | PushKit | APNs |
|---|---|---|
| Тип з’єднання | Постійне TCP (виділений канал) | Спільний канал з буферизацією |
| Медіанна затримка | 120–350 мс | 1–5 секунд |
| Пробудження програми | Завжди, з будь-якого стану | Тільки якщо програма не закрита |
| Розмір payload | До 5 КБ | До 4 КБ |
| Групування iOS | Ні | Так |
Архітектура PushKit побудована навколо PKPushRegistry — об’єкта, який реєструє програму на отримання сповіщень певного типу. Програма створює екземпляр PKPushRegistry, вказує бажаний тип (наприклад, PKPushTypeVoIP) та призначає делегата. Після реєстрації система автоматично підтримує з’єднання з APNs та доставляє push-сповіщення через делегата.
Кожне сповіщення представлене об’єктом PKPushPayload, який містить dictionaryPayload з даними від сервера. Розмір payload обмежений 5 КБ, чого достатньо для передачі метаданих дзвінку: ідентифікатора абонента, типу дзвінку (аудіо/відео), імені контакту та токену сесії. Сам медіапотік передається окремо через WebRTC або інший протокол реального часу.
import PushKit
class PushKitManager: NSObject {
private let pushRegistry = PKPushRegistry(queue: .main)
func configure() {
pushRegistry.delegate = self
pushRegistry.desiredPushTypes = [.voIP]
}
}
PushKit викликає метод делегата при отриманні сповіщення. На цьому етапі програма повинна виділити дані з dictionaryPayload та негайно відобразити виклик через CallKit, інакше система може завершити фонове завдання. Apple рекомендує завершувати обробку протягом 30 секунд, але для VoIP-дзвінків критично важливо відобразити екран виклику протягом першої секунди.
extension PushKitManager: PKPushRegistryDelegate {
func pushRegistry(
_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType
) {
guard let caller =
payload.dictionaryPayload["caller"] as? String
else { return }
CallKitManager.shared.reportIncomingCall(
uuid: UUID(),
handle: caller
)
}
}
З виходом iOS 13 Apple запровадила суворі обмеження на використання PushKit. Розробники масово використовували VoIP-push як прихований механізм для фонового оновлення програм — пробудження через PushKit дозволяло завантажувати контент, синхронізувати дані та оновлювати інтерфейс без явного дозволу користувача. Apple вважала це порушенням концепції енергозбереження та обмежила PushKit лише індикацією вхідних дзвінків.
Тепер кожне PushKit-сповіщення має негайно призводити до відображення вхідного виклику через CallKit. Якщо система виявить, що PushKit використовується для інших цілей — наприклад, для фонової синхронізації або оновлення контенту без відображення виклику — програма може бути відхилена під час модерації або відключена від PushKit-сервісу. Apple також вилучила можливість використання PushKit для фонового оновлення даних починаючи з iOS 13.
Повна інтеграція PushKit включає реєстрацію, отримання push-токена та обробку вхідних сповіщень. PushKit самостійно запитує дозвіл на надсилання сповіщень — додатковий виклик UNUserNotificationCenter не потрібний для самого PushKit, але може знадобитися для локальних сповіщень програми. Після реєстрації система викликає pushRegistry:didUpdatePushCredentials для передачі push-токена, який потрібно надіслати на сервер.
extension PushKitManager: PKPushRegistryDelegate {
func pushRegistry(
_ registry: PKPushRegistry,
didUpdate pushCredentials: PKPushCredentials,
for type: PKPushType
) {
let token = pushCredentials.token
.map { String(format: "%02x", $0) }
.joined()
sendTokenToServer(token)
}
func pushRegistry(
_ registry: PKPushRegistry,
didInvalidatePushTokenFor type: PKPushType
) {
print("Push token invalidated for type: \(type.rawValue)")
}
}
Серверна сторона надсилає PushKit-сповіщення через APNs з push-type = voip та заголовком apns-push-type: voip. На відміну від звичайних APNs, VoIP-push використовує власний сертифікат та не потребує налаштування topic. Payload має містити мінімальні дані для ідентифікації виклику.
// Приклад payload VoIP push
{
"aps": {
"alert": {}
},
"caller": "+15551234567",
"callerName": "Alice Johnson",
"sessionId": "abc-123-def",
"hasVideo": false
}
Налагодження PushKit складніше, ніж стандартних APNs, оскільки PushKit не працює на симуляторі iOS. Для діагностики потрібен фізичний iPhone або iPad. Першою ознакою коректної роботи є виклик pushRegistry:didUpdatePushCredentials при запуску та поява push-токена певного формату (64 шістнадцяткових символів для VoIP). Якщо делегат не викликається, перевірте entitlements вашої програми.
Інша поширена проблема — PushKit не доставляє сповіщення після оновлення програми. Це відбувається, якщо push-токен змінився, але сервер продовжує використовувати старий. Рішення — надсилати свіжий токен на сервер при запуску програми та видаляти недійсні токени при виклику pushRegistry:didInvalidatePushTokenForType. Apple також рекомендує реалізувати механізм аварійного відновлення через звичайні APNs.
| Проблема | Причина | Вирішення |
|---|---|---|
| Не викликається didUpdatePushCredentials | Відсутні entitlements або неправильний тип | Перевірте Capabilities → Push Notifications + VoIP в Xcode |
| Push приходить з затримкою | Пристрій у режимі низького енергоспоживання або слабкий сигнал | PushKit не може обійти апаратні обмеження |
| Не приходять сповіщення після перезавантаження | Зміна push-токена після перевстановлення програми | Запитайте новий токен та оновіть його на сервері |
| App Store відхилив через PushKit | PushKit використовується не для дзвінків | Переконайтеся, що кожен push призводить до reportNewIncomingCall |
Часто запитувані питання
Технічно так, але це немає сенсу. Починаючи з iOS 13, єдине дозволене використання PushKit — індикація вхідних викликів, яка потребує CallKit для відображення. Використання PushKit без CallKit призведе до відхилення програми в App Store.
Максимальний розмір payload для PushKit становить 5 КБ (5120 байт). Це на 1 КБ більше, ніж у звичайних APNs-сповіщеньях, що дозволяє передавати більше метаданих про дзвінок.
Apple автоматично анулює push-токен при видаленні програми. Сервер отримає сповіщення про анулювання та має припинити надсилання push на цей токен. Спроба надіслати push на недійсний токен призведе до помилки APNs 410.
PushKit доступний на macOS 10.14+ для Mac-програм, створених з використанням Mac Catalyst або AppKit. Функціонал повністю аналогічний iOS-версії, включаючи підтримку VoIP-сповіщень.
Використовуйте власну аналітику: відстежуйте час між надсиланням push з сервера та викликом didReceiveIncomingPushWithPayload на клієнті. Середній час менше 500 мс вказує на коректну роботу PushKit.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.