在 iOS 开发中,URL Scheme 和 UIOpenURLContext 是处理应用间通信和深度链接(Deep Linking)的核心技术。以下是它们的详细解释和对比:
一、URL Scheme(URL 方案)#
1. 概念#
- URL Scheme 是一种自定义协议,允许应用通过特定格式的 URL 被其他应用唤醒或传递数据。
- 例如:
myapp://profile?user=123表示调用myapp的 Scheme,并传递参数。
2. 核心用法#
(1) 注册自定义 Scheme#
在 Info.plist 中添加以下配置:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string> <!-- 自定义 Scheme 名称 -->
</array>
</dict>
</array>(2) 处理 Scheme 请求#
在 AppDelegate 中实现方法:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
// 解析 URL,例如:myapp://profile?user=123
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
components.scheme == "myapp",
let queryItems = components.queryItems else {
return false
}
if components.host == "profile" {
let userID = queryItems.first(where: { $0.name == "user" })?.value
// 跳转到用户详情页
return true
}
return false
}3. 调用其他应用#
使用 UIApplication.shared.open 触发其他应用的 Scheme:
if let url = URL(string: "tel://10086") {
UIApplication.shared.open(url)
}4. 常见内置 Scheme#
| Scheme | 用途 | 示例 |
|---|---|---|
tel:// | 拨打电话 | tel://10086 |
mailto:// | 发送邮件 | mailto://support@apple.com |
http:// 或 https:// | 打开网页 | https://www.apple.com |
maps:// | 打开地图 | maps://?q=Beijing |
二、UIOpenURLContext(iOS 13+)#
1. 概念#
- UIOpenURLContext 是 iOS 13 引入的
SceneDelegate中的新 API,用于在多窗口(Multi-Scene)环境下处理 URL 打开请求。 - 替代传统的
AppDelegate方法,支持更精细的场景管理。
2. 核心用法#
(1) 在 SceneDelegate 中处理#
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let urlContext = URLContexts.first else { return }
let url = urlContext.url
// 解析 URL(逻辑与 AppDelegate 类似)
if url.scheme == "myapp" {
// 处理跳转逻辑
}
}(2) 获取额外信息#
let options = urlContext.options
let sourceApp = options.sourceApplication // 来源应用 Bundle ID
let annotation = options.annotation // 附加数据3. 多场景支持#
- 如果应用支持多窗口,可以通过
UIOpenURLContext的scene属性判断来源场景:
if let scene = urlContext.scene as? UIWindowScene {
print("URL 来自场景:\(scene.session.persistentIdentifier)")
}三、URL Scheme 与 UIOpenURLContext 对比#
| 特性 | URL Scheme(传统方式) | UIOpenURLContext(新方式) |
|---|---|---|
| 兼容性 | 所有 iOS 版本 | iOS 13+ |
| 适用场景 | 单窗口应用 | 多窗口应用(如 iPad 分屏) |
| 入口类 | AppDelegate | SceneDelegate |
| 数据获取 | 通过 options 字典 | 通过 UIOpenURLContext 对象 |
| 多窗口处理 | 不支持 | 支持 |
四、安全注意事项#
验证来源应用:
if let sourceApp = options.sourceApplication, sourceApp == "com.legitimate.app" { // 仅处理可信来源 }防止 URL 参数篡改:
// 使用 URLComponents 解析参数,避免手动拼接 guard let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems else { return }白名单配置:
在Info.plist中限制可调用的 Scheme:<key>LSApplicationQueriesSchemes</key> <array> <string>myapp</string> <string>tel</string> </array>
五、替代方案:Universal Links#
- Universal Links 是 Apple 推荐的深度链接方案,比 URL Scheme 更安全(需配置
apple-app-site-association文件)。 - 示例:
https://www.example.com/profile/user123可以直接跳转到应用。
六、完整示例代码#
1. 调用其他应用#
// 拨打电话
if let url = URL(string: "tel://10086"), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
}
// 跳转到 App Store 评分页
if let url = URL(string: "itms-apps://itunes.apple.com/app/id123456?action=write-review") {
UIApplication.shared.open(url)
}2. 处理 Universal Links#
在 SceneDelegate 中:
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL {
// 处理 Universal Link
}
}通过理解 URL Scheme 和 UIOpenURLContext 的原理和用法,您可以实现应用间的无缝跳转和深度链接功能。