iOS URL Scheme 参数如何传递与解析?

99ANYc3cd6
预计阅读时长 24 分钟
位置: 首页 参数 正文

什么是 URL Scheme?

简单回顾一下 URL Scheme 的概念。

ios url scheme 参数
(图片来源网络,侵删)

URL Scheme 是一种自定义的 URL 前缀,格式为 scheme://host/path?query#fragment,它允许你的应用注册一个或多个 Scheme,当用户点击一个带有该 Scheme 的链接时,系统会尝试打开能够处理这个 Scheme 的应用。

一个完整的 URL 结构分解:

scheme://host/path?query#fragment
  • scheme (协议): 必须的,是你的应用的唯一标识符,通常使用你的应用名称或反向域名。myapptwitterfb
  • host (主机): 可选的,用来进一步标识你想要打开应用中的哪个部分。
  • path (路径): 可选的,通常用来传递一些标识符,比如用户 ID、商品 ID 等。
  • query (查询): 可选的,这是传递参数最常见的方式,格式为 key=value,多个参数用 & 分隔。
  • fragment (片段): 可选的,通常用于在已打开的页面内定位到某个特定元素,或者传递一些简单的标识。

如何定义和传递参数?

参数主要通过 QueryPath 两种方式传递。

通过 Query (查询字符串) 传递参数

这是最常用、最灵活的方式,适用于传递多个键值对参数。

ios url scheme 参数
(图片来源网络,侵删)

URL 示例: myapp://product/detail?productId=12345&source=push_notification

  • scheme: myapp
  • host: product
  • path: detail
  • query: productId=12345&source=push_notification
    • productId 是键,12345 是值。
    • source 是键,push_notification 是值。
    • 两个参数用 & 连接。

通过 Path (路径) 传递参数

这种方式通常用于表示一种层级关系或传递一个核心的、唯一的标识符。

URL 示例 1 (单个 ID): myapp://user/98765

  • scheme: myapp
  • host: (无)
  • path: user/98765 (这里的 98765 就是一个参数)

URL 示例 2 (多级路径): myapp://store/category/electronics/item/67890

ios url scheme 参数
(图片来源网络,侵删)
  • scheme: myapp
  • path**:store/category/electronics/item/67890`

    这种方式清晰地表达了导航的层级结构。


如何在 iOS 中处理这些参数?

处理 URL 参数主要分为两个步骤:

  1. 在 Info.plist 中注册 URL Scheme
  2. AppDelegateSceneDelegate 中解析 URL

步骤 1: 注册 URL Scheme

在 Xcode 中,打开你的项目,选择 TARGETS -> Info 标签页,找到 URL Types,点击 添加一个新的 URL Type。

  • URL Schemes: 输入你的 Scheme 名称(myapp),这里可以输入多个,用逗号隔开。
  • URL Identifier: 输入一个唯一的反向域名标识符(com.yourcompany.myapp),这个是必须的,用于区分不同的应用。

步骤 2: 解析和处理 URL

当用户点击你的 Scheme 链接时,系统会调用你的应用的代理方法。

对于 iOS 13 及以上 (使用 SceneDelegate):

// SceneDelegate.swift
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        // 1. 获取被打开的 URL
        guard let url = URLContexts.first?.url else { return }
        // 2. 解析 URL
        handleDeepLink(url: url)
    }
    func handleDeepLink(url: URL) {
        // 3. 检查 Scheme 是否匹配
        guard url.scheme == "myapp" else { return }
        // 4. 解析 Query 参数
        if let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems {
            for item in queryItems {
                if let value = item.value {
                    print("Query Param: \(item.name) = \(value)")
                }
            }
        }
        // 5. 解析 Path
        let pathComponents = url.pathComponents
        print("Path Components: \(pathComponents)")
        // 示例: 处理 myapp://user/98765
        if pathComponents.count == 2 && pathComponents[1] == "user" {
            if let userId = pathComponents.last {
                print("Navigating to user profile with ID: \(userId)")
                // 在这里执行跳转到用户详情页面的逻辑
            }
        }
        // 示例: 处理 myapp://product/detail?productId=12345
        if pathComponents.contains("product") && pathComponents.contains("detail") {
            if let productId = URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems?.first(where: { $0.name == "productId" })?.value {
                print("Navigating to product detail with ID: \(productId)")
                // 在这里执行跳转到商品详情页面的逻辑
            }
        }
    }
}

对于 iOS 13 以下 (使用 AppDelegate):

// AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        // 1. 解析 URL
        handleDeepLink(url: url)
        return true
    }
    func handleDeepLink(url: URL) {
        // ... 解析逻辑与 SceneDelegate 中完全相同 ...
        // (复制上面的 handleDeepLink 函数体即可)
    }
}

高级用法和最佳实践

参数编码

URL 中有些字符(如空格、&、、)是特殊字符,如果直接用在参数值中会导致 URL 解析错误,在生成 URL 时,必须对参数进行编码。

  • Objective-C: 使用 [str stringByAddingPercentEncodingWithAllowedCharacters:]
  • Swift: 使用 str.addingPercentEncoding(withAllowedCharacters:)

示例 (Swift):

let source = "App Store & News"
let encodedSource = source.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let urlString = "myapp://link?source=\(encodedSource)"
print(urlString) // 输出: myapp://link?source=App%20Store%20%26%20News

使用 URLComponents 进行构建和解析

为了更安全、更方便地处理 URL,推荐使用 URLComponents

构建一个复杂的 URL (Swift):

var components = URLComponents()
components.scheme = "myapp"
components.host = "order"
components.path = "/confirm"
// 添加查询参数
components.queryItems = [
    URLQueryItem(name: "orderId", value: "order-xyz-123"),
    URLQueryItem(name: "discount", value: "20%"),
    URLQueryItem(name: "referral", value: "friend_code_abc")
]
if let url = components.url {
    print(url.absoluteString) // 输出: myapp://order/confirm?orderId=order-xyz-123&discount=20%25&referral=friend_code_abc
    // 注意:百分号 % 也会被编码为 %25
}

解析一个 URL (Swift):

let urlString = "myapp://order/confirm?orderId=order-xyz-123&discount=20%25"
if let url = URL(string: urlString),
   let components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
    print("Scheme: \(components.scheme ?? "N/A")")
    print("Host: \(components.host ?? "N/A")")
    print("Path: \(components.path ?? "N/A")")
    if let queryItems = components.queryItems {
        for item in queryItems {
            print("Query: \(item.name) = \(item.value ?? "N/A")")
        }
    }
}

处理 Universal Links (通用链接)

URL Scheme 有一个缺点:当用户设备上没有安装你的应用时,点击链接会弹出一个错误提示,体验很差。

Universal Links (通用链接) 是 Apple 推荐的替代方案,它有巨大优势:

  • 无弹窗:如果应用未安装,链接会在 Safari 中正常打开。
  • 唯一性:不会像 URL Scheme 那样可能被其他应用“劫持”。
  • 安全性:通过关联你的域名和 App ID,确保只有你的应用能处理该链接。

虽然 Universal Links 不使用 scheme:// 格式,但它也支持在路径中传递参数,其解析方式与通过 URLComponents 解析普通网页 URL 完全相同。


特性 URL Scheme Universal Links
格式 myapp://... https://yourdomain.com/...
主要用途 应用间通信、深度链接 深度链接
应用未安装时 弹出错误提示 在 Safari 中打开网页
安全性 可能被其他应用注册相同的 Scheme 高,与域名绑定,唯一性保证
配置 Info.plist 中配置 在 Apple Developer 后台和 Web 服务器上配置
适用场景 需要从其他 App、短信、邮件等地方快速拉起你的 App 官方的、最佳的深度链接方案

对于大多数现代应用,Universal Links 是首选的深度链接方案,但在某些特定场景下,例如从一个已知的、可信的 App(如你的公司另一款 App)中跳转,或者需要实现“返回应用”的功能时,URL Scheme 仍然非常有用,理解如何处理其参数是掌握 iOS 应用间通信的基础。

-- 展开阅读全文 --
头像
星天使儿童智能手表app怎么下载?
« 上一篇 12-09
Linux ftp mget参数有哪些?
下一篇 » 12-09

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]