onOpenURL 是 SwiftUI 提供的一个视图级 URL 打开事件修饰符,用于在 App 通过 URL Scheme 或 Universal Link 被唤起时接收并处理传入的 URL。
本质上是对系统”open URL”事件的SwiftUI封装,对应iOS/macOS的application(_:open:)方法和Apple Events。
基本用法
SwiftUI 代码:
.onOpenURL { url in
print("收到 URL:", url)
}
通常挂在跟视图上:
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
handle(url)
}
}
}
}
也可以对“open URL”事件传入的URL参数进行解析:
.onOpenURL { url in
guard url.scheme == "myapp" else { return }
if url.host == "open" {
let comps = URLComponents(url: url, resolvingAgainstBaseURL: false)
let id = comps?.queryItems?.first(where: { $0.name == "id" })?.value
print("id =", id ?? "")
}
}
url为接收的URL Scheme或者其他URL:
myapp://open?id=123
url.scheme表示协议名,这里对应的是:
myapp
host表示主机部分(在自定义协议中通常作为“功能名/路由名”使用),对应的是:
open
URLComponents可以把字符串URL拆成字段。
使用场景
1、URL Scheme跳转,例如:ImageSlim://open-shared-images。
2、Universal Links,例如:https://fangjunyu.com/open-shared-images。
3、App内模块路由,根据 URL path / query 页面跳转。
4、macOS:从 Finder、其他App触发打开 App 行为。
与AppDelegate区别
在iOS/macOS中,可以使用AppDelegate接收分发的 URL 事件:
// 现代方法:通过 application 接收分发的 URL 事件
func application(_ application: NSApplication, open urls: [URL]) {
print("通过 application(_:open:) 接收到 URL")
for url in urls {
// URL Scheme 分发的事件,例如:ImageSlim://open-shared-images
if url.scheme == "ImageSlim", url.host == "open-shared-images" {
handleSharedImages()
} else {
// 其他分发的事件
fileImporter(urls)
}
}
}
与AppDelegate相比,onOpenURL在SwiftUI视图层,适合SwiftUI项目。AppDelegate在应用生命周期层,适合UIKit/AppKit等项目。
总结
iOS/macOS 通过 URL Scheme等行为打开App时,会触发onOpenURL或者application(_:open:)方法,具体取决于使用场景。
