Настройка App Clips для iOS (мини-приложения)
App Clip — это часть основного приложения весом до 15 МБ, которую пользователь запускает моментально через QR-код, NFC-метку, Safari Banner или ссылку в Maps — без установки полного приложения. Платёж за парковку, быстрый заказ в кафе, регистрация на мероприятие: сценарии, где требование «сначала установи приложение» убивает конверсию.
Архитектура: таргет и shared код
App Clip — отдельный таргет в Xcode (AppClip), не отдельное приложение. Он делит код с основным приложением через shared frameworks или прямое включение файлов в оба таргета. Принципиальное ограничение: App Clip не может обращаться к данным основного приложения (разные sandbox), но может передавать данные при последующей установке через NSUserActivity.
Структура проекта:
MyApp (основной таргет)
├── Sources/
│ ├── SharedFeatures/ ← компилируется в оба таргета
│ └── MainAppOnly/
MyAppClip (App Clip таргет)
└── Sources/
└── ClipEntry.swift
Добавить файл в оба таргета: Build Phases → Compile Sources → добавить общие файлы в MyAppClip.
Info.plist App Clip требует NSAppClip словарь с NSAppClipRequestEphemeralUserNotification и NSAppClipRequestLocationConfirmation — если нужны уведомления и геолокация. Без явного указания Clip не сможет запрашивать эти разрешения.
App Clip Experience URL
Каждый App Clip запускается по URL. URL регистрируется в App Store Connect → App Clips → Add New App Clip Experience. Формат:
https://example.com/clips/parking?lot=A1
В коде App Clip обрабатываем URL через NSUserActivityTypes → NSUserActivityTypeBrowsingWeb:
@main
struct AppClipEntry: App {
var body: some Scene {
WindowGroup {
ContentView()
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { activity in
guard let url = activity.webpageURL else { return }
handleClipURL(url)
}
}
}
func handleClipURL(_ url: URL) {
// Парсим параметры: lot=A1
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
let lot = components?.queryItems?.first(where: { $0.name == "lot" })?.value
// Открываем нужный экран
}
}
URL-ассоциация настраивается через apple-app-site-association файл на сервере:
{
"appclips": {
"apps": ["TEAMID.com.example.myapp.Clip"]
}
}
Файл должен быть доступен по https://example.com/.well-known/apple-app-site-association с Content-Type application/json.
Платежи и авторизация в App Clip
Apple Pay — работает в App Clip без ограничений. Именно поэтому платёжные сценарии — основное применение Clips. PKPaymentAuthorizationViewController подключается стандартно.
Sign in with Apple — работает. Важно: пользователь получает эфемерный идентификатор для App Clip, отличный от идентификатора в основном приложении. При установке полного приложения нужно обработать миграцию через SKOverlay:
// Предложить установку полного приложения после успешного действия
let config = SKOverlay.AppClipConfiguration(position: .bottom)
let overlay = SKOverlay(configuration: config)
overlay.present(in: windowScene)
Ephemeral notifications — App Clip может попросить разрешение на уведомления без стандартного системного диалога разрешений, но только на время сессии Clip (8 часов). Запрашиваются через NSAppClipRequestEphemeralUserNotification.
Тестирование
Локальное тестирование: схема MyAppClip + environment variable _XCAppClipURL с тестовым URL. Xcode запускает Clip в режиме симуляции без необходимости регистрации в App Store Connect.
Scheme Environment Variables:
_XCAppClipURL = https://example.com/clips/parking?lot=A1
Тестирование через TestFlight: полный App Clip опыт с реальным QR/NFC — только через TestFlight или продакшн. Симулятор не поддерживает NFC.
Ограничения, о которых нужно знать
- Нет доступа к HealthKit, HomeKit, CallKit
- Нет фоновых задач (Background Tasks)
- CloudKit доступен только для чтения публичных записей
- Размер 15 МБ — после компрессии App Store, не размер бандла в проекте
Ориентиры по срокам
Настройка App Clip таргета, URL association, базовый флоу с Apple Pay — 3 дня. Полноценный сценарий с передачей данных в основное приложение, SKOverlay, тестированием через TestFlight — 4–5 дней.







