← Назад к вопросам

Как можно реализовать DeepLink?

2.3 Middle🔥 112 комментариев
#Архитектура и паттерны

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация DeepLink в iOS

DeepLink (или глубокое связывание) — это техника, позволяющая открывать конкретные разделы или выполнять определенные действия внутри приложения через специальные URL. В iOS это реализуется через Universal Links (для веб-сайтов) и Custom URL Schemes (для внутренних ссылок).

Основные подходы

1. Custom URL Schemes

Это собственные схемы URL, которые ваше приложение регистрирует в системе. Они используются для открытия приложения из других приложений или системных компонентов.

Регистрация схемы в Info.plist:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
        </array>
        <key>CFBundleURLName</key>
        <string>com.example.MyApp</string>
    </dict>
</array>

Обработка ссылки в AppDelegate:

func application(_ app: UIApplication, 
                 open url: URL, 
                 options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
          let queryItems = components.queryItems else {
        return false
    }
    
    // Пример: myapp://product?id=123
    if url.scheme == "myapp" && url.host == "product" {
        let productId = queryItems.first(where: { $0.name == "id" })?.value
        if let id = productId {
            navigateToProductDetail(id: id)
        }
        return true
    }
    
    return false
}

2. Universal Links

Это более современный и безопасный подход, использующий HTTPS-ссылки для открытия приложения. Они требуют конфигурации на стороне сервера и в приложении.

Конфигурация в Info.plist:

<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:example.com</string>
</array>

Создание файла apple-app-site-association на сервере:

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "TEAMID.com.example.MyApp",
                "paths": ["/products/*", "/profile"]
            }
        ]
    }
}

Обработка в SceneDelegate или AppDelegate:

func scene(_ scene: UIScene, 
           willConnectTo session: UISceneSession, 
           options connectionOptions: UIScene.ConnectionOptions) {
    
    if let urlContext = connectionOptions.urlContexts.first {
        handleUniversalLink(url: urlContext.url)
    }
}

func application(_ application: UIApplication, 
                 continue userActivity: NSUserActivity, 
                 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
        guard let url = userActivity.webpageURL else { return false }
        return handleUniversalLink(url: url)
    }
    return false
}

private func handleUniversalLink(url: URL) -> Bool {
    // Пример: https://example.com/products/123
    if url.pathComponents.contains("products") {
        let productId = url.lastPathComponent
        navigateToProductDetail(id: productId)
        return true
    }
    return false
}

Ключевые этапы реализации

Подготовка

  • Определите схему ссылок: продумайте структуру URL (например, myapp://section/item?id=123 или https://domain.com/path).
  • Настройте проекты: добавьте необходимые записи в Info.plist, конфигурационные файлы на сервере.

Обработка

  • Разберите URL: используйте URLComponents для декомпозиции ссылки на компоненты (scheme, host, path, query).
  • Валидация: проверьте соответствие схемы/домена вашим ожиданиям.
  • Маршрутизация: на основе параметров URL выполните переход к нужному экрану или действию.

Навигация

private func navigateToProductDetail(id: String) {
    guard let window = UIApplication.shared.windows.first,
          let rootVC = window.rootViewController as? UINavigationController else {
        return
    }
    
    let productVC = ProductDetailViewController(productId: id)
    rootVC.pushViewController(productVC, animated: true)
}

Рекомендации и best practices

  • Используйте Universal Links для внешних ссылок: они более безопасны и предоставляют лучший пользовательский опыт (переход напрямую в приложение без промежуточных диалогов).
  • Custom URL Schemes для внутренних коммуникаций: например, для открытия из других ваших приложений или обработки специфических команд.
  • Всегда проверяйте параметры: DeepLink может быть потенциальным вектором атак, поэтому валидируйте все входные данные.
  • Обрабатывайте edge cases: предусмотрите случаи, когда приложение еще не полностью запущено или нужный экран не готов.
  • Логирование: добавляйте логи для отслеживания успешных и неудачных открытий через DeepLink — это поможет в диагностике проблем.
  • Тестирование: создайте unit-тесты для парсинга URL и интеграционные тесты для проверки полного цикла открытия приложения.

Пример комплексной обработки

class DeepLinkRouter {
    
    enum DeepLinkType {
        case productDetail(id: String)
        case userProfile(userId: String)
        case settings(section: String)
    }
    
    func parse(url: URL) -> DeepLinkType? {
        let components = URLComponents(url: url, resolvingAgainstBaseURL: true)
        
        // Обработка Universal Link
        if url.scheme == "https" && url.host == "example.com" {
            if url.path.hasPrefix("/products/") {
                let productId = url.lastPathComponent
                return .productDetail(id: productId)
            }
        }
        
        // Обработка Custom URL Scheme
        if url.scheme == "myapp" {
            switch url.host {
            case "product":
                let queryItems = components?.queryItems
                let productId = queryItems?.first(where: { $0.name == "id" })?.value
                if let id = productId {
                    return .productDetail(id: id)
                }
            case "profile":
                // аналогичная обработка
                break
            }
        }
        
        return nil
    }
    
    func navigate(to linkType: DeepLinkType) {
        switch linkType {
        case .productDetail(let id):
            presentProductDetail(id: id)
        // обработка других случаев
        }
    }
}

Реализация DeepLink требует внимательности к деталям, но значительно улучшает интеграцию приложения с экосистемой iOS и внешними сервисами, предоставляя пользователям seamless опыт перехода между web и app контентом.

Как можно реализовать DeepLink? | PrepBro