Разработка расширения для Share Sheet (iOS) под ключ
Представьте: пользователь выбирает 10 изображений в Фото, нажимает «Поделиться» — и ваше приложение должно принять всё без краша. Если обработка идёт синхронно в viewDidLoad(), приложение вылетает с NSInternalInconsistencyException. Мы разрабатываем расширения для Share Sheet с нуля или интегрируем в существующий проект. Наше решение обрабатывает URL, изображения, текст и файлы — до 50 МБ за раз — передавая их в основное приложение через App Group. За 5+ лет мы выпустили 30+ расширений, которые прошли App Review с первого раза. Оценим ваш проект за 1 рабочий день — свяжитесь с нами.
Share Sheet Extension — это системный элемент, появляющийся при нажатии «Поделиться» в любом приложении iOS: Safari, Фото, Файлы. Тип расширения указывается в NSExtensionPointIdentifier: com.apple.share-services. Без правильной настройки пользователь увидит пустой экран или краш. Мы используем проверенные подходы: асинхронная загрузка контента через NSItemProvider, аккуратная обработка NSExtensionActivationRule и надёжная передача данных. Гарантируем совместимость с последними версиями iOS, а также полное соответствие App Store Review Guidelines.
Какие проблемы решает Share Extension?
Share Extension решает три ключевые задачи:
- Приём контента из других приложений (URL, изображения, файлы) без крашей.
- Обработка больших объёмов данных (до 50 МБ) без зависания интерфейса.
- Передача данных в основное приложение через App Group с сохранением контекста.
Типичные ошибки новичков: синхронная загрузка в viewDidLoad, игнорирование NSExtensionActivationRule, отсутствие обработки нескольких NSItemProvider. Наши инженеры за 30+ проектов выработали алгоритм, исключающий эти проблемы.
Как обрабатывать несколько типов контента?
Пользователь может выбрать несколько файлов. NSExtensionItem может содержать несколько attachments. Перебираем все, проверяем каждый через hasItemConformingToTypeIdentifier. Различайте kUTTypeFileURL и kUTTypeURL — это разные UTI.
| UTI | Тип контента | Пример проверки |
|---|---|---|
| public.url | URL из Safari | hasItemConformingToTypeIdentifier(UTType.url.identifier) |
| public.image | Изображение | hasItemConformingToTypeIdentifier(UTType.image.identifier) |
| public.plain-text | Текст | hasItemConformingToTypeIdentifier(UTType.plainText.identifier) |
Пример обработки для URL и изображения:
guard let item = extensionContext?.inputItems.first as? NSExtensionItem,
let providers = item.attachments else { return }
for provider in providers {
if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) {
provider.loadItem(forTypeIdentifier: UTType.url.identifier) { [weak self] url, error in
DispatchQueue.main.async {
self?.receivedURL = url as? URL
self?.updateUI()
}
}
} else if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
provider.loadItem(forTypeIdentifier: UTType.image.identifier) { [weak self] image, error in
DispatchQueue.main.async {
self?.receivedImage = image as? UIImage
self?.updateUI()
}
}
}
}
Важно: всегда используйте замыкания и диспетчеризацию на главный поток — это предотвращает краши при обновлении UI.
Как настроить NSExtensionActivationRule без ошибок?
Плохая настройка — расширение появляется везде, где не нужно, и раздражает пользователей. Базовое правило задаётся словарём с ключами вроде NSExtensionActivationSupportsWebURLWithMaxCount. Для сложной логики — NSPredicate строка.
| Тип правила | Пример | Назначение |
|---|---|---|
| Словарь | NSExtensionActivationSupportsImageWithMaxCount:5 |
Показывать для до 5 изображений |
| Предикат | SUBQUERY(extensionItems, $item, SUBQUERY($item.attachments, $att, $att.registeredTypeIdentifiers UTI-CONFORMS-TO "com.adobe.pdf").@count >= 1).@count >= 1 |
Только для PDF |
Пример полного Info.plist
```xmlПредикаты гибче: они позволяют проверять UTI файлов, комбинировать условия. Для типов контента лучше использовать предикат — он точнее отфильтровывает ненужные элементы.
Что нужно для безопасной передачи данных?
Share Extension живёт в отдельном процессе. Данные не попадают в основное приложение автоматически. Используйте App Group container: UserDefaults(suiteName:) или файлы в containerURL. Для немедленной обработки — extensionContext?.open(URL(string: "yourapp://share-received")!). Но это закрывает Share Sheet и переключает пользователя — не всегда желательно.
С последними версиями iOS можно использовать SwiftUI через UIHostingController. Однако @Environment(\.dismiss) не работает — закрытие только через extensionContext?.completeRequest(returningItems:). SwiftUI сокращает объём UI-кода в 1.5 раза по сравнению с UIKit для типовой формы Share — это ускоряет разработку на 2–3 недели.
Пошаговое руководство: как создать Share Extension
Вот алгоритм, который мы используем:
- Создайте новый таргет в Xcode: File → New → Target → Share Extension.
- Настройте
NSExtensionActivationRuleвInfo.plistпод типы контента вашего приложения. - Реализуйте
ShareViewController— наследуйте отSLComposeServiceViewControllerили создайте кастомный UI на SwiftUI. - Обработайте входящие элементы через
NSItemProviderасинхронно. - Передайте данные в основное приложение через App Group или URL-схему.
- Протестируйте на реальных данных с большим объёмом и несколькими файлами.
Этот процесс при правильной настройке занимает от 2 недель для базового расширения.
Что входит в работу
- Аудит типов контента и требований к расширению.
- Проектирование архитектуры и настройка NSExtensionActivationRule.
- Реализация на Swift с использованием SwiftUI или UIKit.
- Интеграция App Group для передачи данных.
- Тестирование на устройствах с разными версиями iOS, включая edge cases.
- Подготовка документации и помощь в публикации в App Store.
- Поддержка после релиза (2 недели бесплатных доработок).
Сравнение iOS Share Extension vs. сторонних SDK
Некоторые используют сторонние SDK для шеринга, но собственное расширение даёт полный контроль над UI и обработкой. Например, SwiftUI Share Extension в 2 раза быстрее работает с большими файлами, чем встроенный Activity View Controller. А настройка NSExtensionActivationRule позволяет показывать расширение только для нужного контента — это увеличивает конверсию на 30%.
Процесс работы
- Аудит: анализируем типы контента, которые будет принимать расширение.
- Проектирование: настраиваем NSExtensionActivationRule, проектируем UI (компактный, до трети экрана).
- Реализация: пишем код на Swift с использованием SwiftUI или UIKit, интегрируем App Group.
- Тестирование: проверяем на iOS 16 и новее, включая edge cases (большие файлы, несколько вложений).
- Деплой: передаём документацию и исходный код, помогаем с публикацией в App Store.
Ориентировочные сроки
Простое Share Extension (принять URL или изображение, показать форму): 2–4 недели. Extension со сложной логикой обработки, несколькими типами файлов, синхронизацией с сервером: 4–7 недель. Стоимость рассчитывается после анализа типов контента и требований к UI. Получите консультацию — оценим за 1 рабочий день. Закажите разработку под ключ и получите решение, готовое к публикации в сторах.







