Розробка розширення для 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 робочий день. Замовте розробку під ключ і отримайте рішення, готове до публікації в сторах.







