在 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 的原理和用法,您可以实现应用间的无缝跳转和深度链接功能。