Реализация Universal Links для iOS-приложения
Universal Links — механизм, при котором ссылка вида https://example.com/product/123 открывает приложение напрямую на нужном экране, минуя браузер. Если приложение не установлено — открывается сайт. Никаких кастомных схем (myapp://product/123), которые не работают в Safari и блокируются корпоративными MDM.
Как это работает и где ломается
AASA-файл. На сервере по адресу https://example.com/.well-known/apple-app-site-association должен лежать JSON без расширения файла, с заголовком Content-Type: application/json, доступный по HTTPS без редиректов. Apple парсит этот файл при установке приложения и кэширует на CDN — обновление может занять до 24 часов.
Самая частая ошибка: сервер отдаёт файл с редиректом с http на https, или с 301 на www-версию домена. Apple не следует редиректам при скачивании AASA. Проверяем через curl -v https://example.com/.well-known/apple-app-site-association — должен вернуть 200 с правильным Content-Type.
Формат для iOS 13+ (applinks с details):
{
"applinks": {
"details": [{
"appIDs": ["TEAMID.com.example.app"],
"components": [
{ "/": "/product/*", "comment": "Product pages" },
{ "/": "/order/*" }
]
}]
}
}
App Entitlements. В Entitlements.plist нужен com.apple.developer.associated-domains с записью applinks:example.com. Забытый entitlement — приложение просто не получает universal link колбек.
Обработка в коде. В AppDelegate или SceneDelegate реализуем application(_:continue:restorationHandler:) (UIKit) или onOpenURL (SwiftUI). Получаем NSUserActivity с типом NSUserActivityTypeBrowsingWeb и webpageURL. Парсим путь, определяем нужный экран, строим навигационный стек.
Разбор URL должен быть устойчивым: webpageURL может прийти с query-параметрами, фрагментами, в верхнем регистре. Используем URLComponents вместо ручного разбора строк.
Тестирование. В симуляторе universal links работают через xcrun simctl openurl booted 'https://example.com/product/123'. На реальном устройстве — через Safari (долгое нажатие на ссылку → «Открыть в приложении»). Xcode → Diagnostics не покажет проблему с AASA — нужен swcutil на Mac и Console.app для логов swcd (Apple's universal links daemon).
Сценарии и edge-cases
Associated Domains Alternate Mode. Для enterprise-приложений или staging-окружений добавляем applinks:example.com?mode=developer в entitlements. В developer mode iOS не кэширует AASA и запрашивает файл напрямую с сервера — удобно при разработке.
Несколько доменов. Приложение может обрабатывать несколько доменов — просто добавляем несколько записей в entitlements. AASA нужен на каждом домене отдельно.
Ссылки из email-клиентов. Gmail и Outlook в приложениях на iOS оборачивают ссылки через свой redirect-сервис. Universal link в этом случае не срабатывает — Apple видит redirect URL, а не целевой. Это ограничение platform-side, не баг в реализации.
Что входит в работу
- Настройка AASA-файла на сервере с нужными паттернами путей
- Entitlements и конфигурация в Xcode для всех таргетов и схем (Debug, Release, Staging)
- Реализация обработчика в
SceneDelegate/AppDelegateс роутингом на нужные экраны - Тестирование на реальных устройствах и через симулятор
- Проверка через Apple's validator (AASA Validator)
Сроки
Реализация с несколькими паттернами путей и интеграцией в существующую навигацию: 1–2 дня. С поддержкой нескольких доменов и кастомной логикой роутинга — 2–3 дня. Стоимость рассчитывается индивидуально.







