Уявіть: ваш iOS-віджет показує вчорашні дані, тому що не бачить оновлення з основного додатка. Або Siri Intent видає «Немає доступу до налаштувань». Це не баг — це ізоляція пісочниці iOS. App Groups — єдиний легальний спосіб організувати спільне сховище між додатком і його розширеннями. Ми налаштовували його для 40+ проєктів і знаємо всі підводні камені. Гарантуємо коректну синхронізацію та документацію. Економія на налагодженні синхронізації — до 40 % часу розробки. У 90 % випадків проблема вирішується за один день. Отримайте консультацію з налаштування App Groups для вашого проєкту.
Як налаштувати App Groups для обміну даними?
Налаштування починається на порталі розробника: створіть App Group з ідентифікатором, наприклад group.com.yourcompany.yourapp, і додайте його в профілі provisioning для кожного таргета. У Xcode увімкніть Capability "App Groups" у всіх цілях (додаток і кожне розширення) і виберіть одну й ту саму групу. Без цього розширення не побачить спільного контейнера. Докладніше — Apple Developer Documentation з App Groups entitlement.
Три способи спільного сховища
| Спосіб | Тип даних | Продуктивність | Складність |
|---|---|---|---|
| UserDefaults (suiteName) | примітиви, рядки, Data | висока | низька |
| File container (JSON, plist) | файли, серіалізовані об'єкти | середня | середня |
| Core Data (shared store) | структуровані дані, relationships | залежить від розміру | висока |
Вибір залежить від задачі: для простих прапорців і лічильників достатньо UserDefaults, для складних об'єктів — файли або Core Data. Наприклад, UserDefaults швидший за Core Data в 10 разів для простих даних, але Core Data забезпечує цілісність при зверненні з відношеннями. Для віджетів з частими оновленнями (частіше 15 хвилин) кращий UserDefaults — він легший і швидший.
Shared UserDefaults на практиці
let sharedDefaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp") sharedDefaults?.set("active", forKey: "userStatus") sharedDefaults?.synchronize() // Явний flush — важливо перед виходом extension У розширенні читаєте так само. Без suiteName стандартний UserDefaults бачить лише свою пісочницю. Перевірено на актуальних версіях iOS — поведінка стабільна.
Shared Container для файлів
let containerURL = FileManager.default.containerURL( forSecurityApplicationGroupIdentifier: "group.com.yourcompany.yourapp" )! let fileURL = containerURL.appendingPathComponent("shared_data.json") // Запис try data.write(to: fileURL) // Читання в extension let sharedData = try Data(contentsOf: fileURL) Для Core Data з shared store: NSPersistentContainer ініціалізується з URL із containerURL(forSecurityApplicationGroupIdentifier:). В одному з проєктів ми мігрували 8 таргетів на спільний Core Data store — час синхронізації скоротився в 3 рази.
WidgetKit: отримання даних з App Group
WidgetKit Timeline Provider працює в окремому процесі. Щоб отримати актуальні дані для віджета:
struct Provider: TimelineProvider { func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) { let defaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp")! let count = defaults.integer(forKey: "pendingTasksCount") let entry = TaskEntry(date: Date(), count: count) let timeline = Timeline(entries: [entry], policy: .atEnd) completion(timeline) } } З основного додатка при оновленні даних: WidgetCenter.shared.reloadAllTimelines() — сигнал віджету перерахувати timeline. Цей метод обов'язковий для негайного оновлення віджета. Без нього віджет перезавантажиться лише через найближчий timeline refresh (зазвичай 15–60 хвилин).
Чому дані не синхронізуються між додатком і розширенням?
Типові причини: різні ідентифікатори групи в таргетах, відсутність виклику synchronize() у UserDefaults, неправильний шлях до файлового контейнера, або розширення не додане в ту ж групу. Також перевірте, що WidgetCenter.reloadAllTimelines() викликається після оновлення даних. У 80 % звернень проблема вирішується простим додаванням App Groups capability у налаштуваннях проєкту. Ми включаємо в роботу аудит існуючих налаштувань і тестування сценаріїв синхронізації.
Що входить у роботу
- Аудит поточних налаштувань App Groups і provisioning profiles.
- Конфігурація code signing для всіх таргетів (генеруємо сертифікати та профілі, якщо потрібно).
- Реалізація спільного сховища: UserDefaults, файловий контейнер або Core Data — під вашу задачу.
- Інтеграція з WidgetKit, Siri Intents, Share Extensions — будь-якими розширеннями.
- Написання та документування коду (ви отримуєте готові модулі).
- Тестування синхронізації: фонове оновлення, завершення процесу, перезавантаження пристрою — мінімум 20 сценаріїв.
- Надання документації з підтримки та експлуатації.
Типова архітектура спільного контейнера
- Основний додаток записує дані в спільний UserDefaults та/або файловий контейнер.
- Розширення (віджет, Siri Intent) читає дані з того ж контейнера.
- Для Core Data: всі таргети використовують один NSPersistentStoreCoordinator з URL у контейнері.
- Синхронізація: після запису в основному додатку викликається
WidgetCenter.reloadAllTimelines()для віджетів іINInteraction donateдля Siri.
Порівняння підходів для різних типів розширень
| Тип розширення | Рекомендований спосіб | Продуктивність |
|---|---|---|
| Widget (WidgetKit) | UserDefaults або файли (JSON) | висока |
| Siri Intent | UserDefaults або Core Data | середня |
| Share Extension | Файловий контейнер (зображення, документи) | середня |
| Custom Keyboard | UserDefaults | низька (обмежена пам'ять) |
Процес роботи
- Аналітика: розбираємо вашу архітектуру, виявляємо точки обміну даними. Часто клієнти не враховують фонові оновлення та завершення процесу.
- Проектування: визначаємо оптимальний спосіб (UserDefaults / файли / Core Data) для кожного сценарію. Наприклад, для віджета з частими оновленнями — UserDefaults, для історії замовлень — Core Data.
- Реалізація: вмикаємо App Groups, конфігуруємо provisioning, пишемо код. На цьому етапі вирішуємо проблеми з code signing і entitlements.
- Тестування: перевіряємо синхронізацію в різних сценаріях (фоновий режим, завершення процесу, перезавантаження пристрою). Використовуємо TestFlight для реальних пристроїв.
- Деплой: готуємо App Store публікацію з коректними entitlements. Надаємо документацію з підтримки.
Орієнтовні терміни
Налаштування App Groups для двох таргетів — від 1 робочого дня, для складних схем з Core Data та кількома розширеннями — до 3 днів. Вартість розраховується індивідуально після оцінки проєкту. Зв'яжіться з нами для аудиту вашого проєкту — ми подивимося, які розширення потребують спільного доступу до даних, і запропонуємо оптимальне рішення. Замовте послугу — ви отримаєте готову інтеграцію з повним набором тестів та документації.







