App Group — это механизм iOS, который создаёт общий контейнер для обмена данными между приложением и его расширениями. Без него каждый процесс (основное приложение, виджет, share extension) работает в изолированной песочнице и не имеет доступа к данным соседнего компонента. По данным Apple Developer Documentation, 2026, App Group решает эту проблему через единый идентификатор группы, который указывается в entitlements. Это фундаментальный инструмент для создания согласованного пользовательского опыта в iOS-экосистеме.
Главное
App Group — это механизм операционной системы iOS, который предоставляет общую область хранения для нескольких процессов одного разработчика. Без него каждое расширение работает в собственной песочнице и не может прочитать данные, которые записал другой компонент. App Group решает эту изоляцию, создавая директорию на файловой системе, доступную всем процессам с корректными entitlements.
Идентификатор группы начинается с префикса group. и указывается в файле entitlements проекта. В Xcode этот идентификатор добавляется через Capabilities — система автоматически включает его в подпись приложения. После настройки все участники группы получают доступ к общей директории по пути Library/Application Support/ внутри контейнера.
По данным Apple WWDC 2020 Session 10026, App Group покрывает три ключевых сценария: синхронизация настроек через NSUserDefaults, общий доступ к файлам через FileManager и совместное использование Core Data с единым хранилищем. Для каждого сценария требуется лишь указать идентификатор группы в соответствующем API.
iOS создаёт общий контейнер при первом запуске любого процесса, который имеет entitlement com.apple.security.application-groups. Физически контейнер располагается в системной директории — его путь отличается от песочницы основного приложения и расширений, но все авторизованные процессы имеют права на чтение и запись.
Apple гарантирует безопасность App Group через связку team ID и подписи кода. Процесс, не подписанный тем же сертификатом разработчика, не может получить доступ к контейнеру группы. Это предотвращает утечку данных между приложениями разных разработчиков.
Формат идентификатора: group.<team-id>.<name>. Например, group.ABC123DEFG.widget-data. На одном устройстве можно создать несколько групп, каждая со своим набором участников. Одно приложение может входить в несколько App Group одновременно — это полезно для разделения данных разных расширений.
// Get the App Group container URL
guard let containerURL = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.widget")
else { return }
// Create a file in the shared container
let fileURL = containerURL.appendingPathComponent("shared.data")
try "Hello from main app".write(to: fileURL, atomically: true, encoding: .utf8)
FileManager предоставляет метод containerURL(forSecurityApplicationGroupIdentifier:), который возвращает URL общей директории. Важно вызывать этот метод в каждом процессе отдельно — путь физически одинаков, но каждый процесс видит его через собственную призму безопасности.
Включение App Group в Xcode начинается с Capabilities — переключатель App Groups добавляет entitlement в проект. Apple Developer Portal также требует, чтобы идентификатор приложения включал эту capability. Без неё подпись кода не сработает на реальном устройстве.
Откройте проект в Xcode, выберите таргет приложения и перейдите на вкладку Signing & Capabilities. Нажмите + и выберите App Groups. Создайте или выберите существующую группу. Повторите те же шаги для каждого расширения, которое должно иметь доступ к общему контейнеру. Все участники должны использовать один и тот же идентификатор группы.
После включения Capabilities Xcode автоматически создаёт файл .entitlements с ключом com.apple.security.application-groups и массивом идентификаторов. Убедитесь, что все необходимые расширения имеют этот файл с корректным team ID в идентификаторе группы.
<!-- Example entitlements file -->
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.example.shared</string>
</array>
Если в вашем проекте несколько расширений (Today Widget, Share Extension, Notification Service), каждое должно иметь собственный файл entitlements с той же группой. Отсутствие entitlements у любого таргета — частая причина, по которой расширение не видит общие данные.
Самый простой способ синхронизации данных между приложением и расширениями — UserDefaults с указанием suite name. Вместо стандартного UserDefaults.standard вы создаёте экземпляр с идентификатором App Group, и все процессы читают одни и те же настройки.
По данным Apple Human Interface Guidelines, этот механизм подходит для синхронизации состояния: выбранной темы, избранных элементов, флагов онбординга. Однако он не предназначен для больших объёмов данных или конкурентных операций записи — для этого используйте файлы или Core Data.
// Write to UserDefaults App Group (main app)
let defaults = UserDefaults(suiteName: "group.com.example.shared")
defaults?.set(true, forKey: "isDarkMode")
defaults?.synchronize()
// Read from UserDefaults App Group (widget extension)
let sharedDefaults = UserDefaults(suiteName: "group.com.example.shared")
let isDark = sharedDefaults?.bool(forKey: "isDarkMode") ?? false
Обратите внимание: экземпляр UserDefaults с suiteName создаётся в каждом процессе отдельно, но читает из одного plist-файла в общем контейнере. Метод synchronize() гарантирует немедленную запись на диск — в iOS 13+ его можно опустить, так как система синхронизирует данные периодически.
Для более сложных сценариев App Group предоставляет доступ к общей файловой системе. Любой файл, созданный в директории контейнера, доступен всем процессам группы. Это позволяет реализовать общую базу Core Data, кэш изображений или временные файлы.
Чтобы использовать общее Core Data хранилище, создайте NSPersistentContainer с URL файла .sqlite, расположенного в директории App Group. Убедитесь, что только один процесс пишет в базу единовременно — конкурентная запись может повредить данные. Типичная архитектура: основное приложение пишет, расширения читают.
// Setup Core Data with App Group container
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "SharedModel")
guard let appGroupURL = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.shared")
else { return container }
let storeURL = appGroupURL.appendingPathComponent("SharedModel.sqlite")
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
container.loadPersistentStores { _, error in
if let error = error { fatalError(error.localizedDescription) }
}
return container
}()
Альтернативный подход — файловый кэш изображений. NSCache живёт только в памяти, но через App Group можно сохранять закэшированные изображения на диск в общую директорию. Расширение виджета получает доступ к тем же файлам и отображает актуальные данные без дополнительной загрузки из сети.
| Сценарий | Рекомендуемый API | Размер данных |
|---|---|---|
| Настройки и флаги | UserDefaults suiteName | до 1 КБ |
| Кэш изображений | FileManager + NSCache | до 100 МБ |
| Структурированные данные | Core Data store | до 500 МБ |
| Временные файлы | FileManager temporary | до 50 МБ |
При работе с общими файлами учитывайте, что система может выгрузить расширение в любой момент. Используйте NSFileCoordinator для координации доступа, чтобы избежать повреждения данных при одновременной записи разными процессами.
Часто задаваемые вопросы
App Group — это механизм iOS, который создаёт общий контейнер для хранения данных между приложением и его расширениями. Он позволяет процессам с одинаковым идентификатором группы обмениваться файлами, настройками UserDefaults и данными Core Data через единую директорию на файловой системе.
Откройте Capabilities таргета в Xcode, включите App Groups и добавьте идентификатор в формате group.*. Затем повторите те же шаги для каждого расширения, которое должно иметь доступ к общему контейнеру. Убедитесь, что все участники используют одинаковый идентификатор группы.
Все типы расширений iOS поддерживают App Group: Today Widget (widget extension), Share Extension, Notification Service Extension, Custom Keyboard и другие. Каждое расширение должно иметь отдельный файл entitlements с тем же идентификатором группы, что и основное приложение.
Да, но только если приложения подписаны одним и тем же сертификатом разработчика и имеют одинаковый team ID. Apple гарантирует безопасность через подпись кода: два приложения от разных разработчиков не могут получить доступ к одному контейнеру даже с одинаковым идентификатором группы.
Используйте UserDefaults с suite name для небольших настроек, FileManager для файлов и Core Data для структурированных данных. Все эти API работают с директорией App Group — достаточно указать идентификатор группы при инициализации. Для Core Data убедитесь, что URL хранилища указывает на общую директорию.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также