Logo
Section 1 / 6

移动应用中的深度链接与通用链接

探索深度链接和通用链接作为跨越移动客户端、操作系统和后端服务的分布式系统。学习域名验证、集中式 URL 路由以及延迟深度链接如何协同工作,实现从外部来源到应用内内容的确定性导航。

检查点

移动应用中的深度链接与通用链接

探索深度链接和通用链接作为跨越移动客户端、操作系统和后端服务的分布式系统。学习域名验证、集中式 URL 路由以及延迟深度链接如何协同工作,实现从外部来源到应用内内容的确定性导航。

App stateOS delivery mechanismKey challengeRecommended pattern
Cold startLaunch parameter / initial intentAuth gates and dependency readiness may block navigationQueue deep link intent, process after initialization completes
BackgroundLifecycle callback (continueUserActivity / onNewIntent)Reconciling with existing navigation back stackUse NavigationCoordinator to decide push, replace, or reset
ForegroundSame lifecycle callback, app is activeRace conditions with in-progress transitionsDebounce or serialize navigation commands through a central router
1import Foundation 2import UIKit 3 4// Typed representation of all supported deep-link destinations 5enum Route { 6 case product(id: String) 7 case profile(userId: String) 8 case home 9} 10 11class DeepLinkRouter { 12 13 // MARK: - Resolve 14 15 /// Parses a URL into a Route, returning nil for unrecognized or invalid links. 16 func resolve(url: URL) -> Route? { 17 guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { 18 return nil // Malformed URL 19 } 20 21 let path = components.path // e.g. "/product", "/profile", "/" 22 let queryItems = components.queryItems ?? [] 23 24 // Helper: extract a named query parameter value 25 func queryValue(for name: String) -> String? { 26 queryItems.first(where: { $0.name == name })?.value 27 } 28 29 // Whitelist pattern matching — only explicitly listed paths are accepted 30 switch path { 31 case "/product": 32 guard 33 let id = queryValue(for: "id"), 34 isValidProductID(id) // Sanitize: non-empty, alphanumeric only 35 else { return nil } 36 return .product(id: id) 37 38 case "/profile": 39 guard 40 let userId = queryValue(for: "userId"), 41 !userId.isEmpty // Basic non-empty validation 42 else { return nil } 43 return .profile(userId: userId) 44 45 case "/", "/home": 46 return .home 47 48 default: 49 return nil // Reject any unrecognized path 50 } 51 } 52 53 // MARK: - Navigate 54 55 /// Dispatches UI navigation based on the resolved route. 56 func navigate(to route: Route) { 57 switch route { 58 case .product(let id): 59 // Push product detail screen with sanitized ID 60 print("Navigating to product: \(id)") 61 62 case .profile(let userId): 63 // Push profile screen for the given user 64 print("Navigating to profile: \(userId)") 65 66 case .home: 67 // Pop to root / show home tab 68 print("Navigating to home") 69 } 70 } 71 72 // MARK: - Private Helpers 73 74 /// Validates that a product ID is non-empty and contains only alphanumeric characters. 75 private func isValidProductID(_ id: String) -> Bool { 76 guard !id.isEmpty else { return false } 77 // Parameter sanitization: reject anything outside [A-Za-z0-9] 78 let alphanumeric = CharacterSet.alphanumerics 79 return id.unicodeScalars.allSatisfy { alphanumeric.contains($0) } 80 } 81}

Quiz

单选题

Universal Links 和 App Links 相比自定义 URI 方案的主要安全优势是什么?

1 / 2

移动应用中的性能优化

移动应用的特性标志与远程配置