Apple Watch自定义Deep Link无法启动应用的技术求助
问题概述
已在iOS端成功实现通过自定义URL Scheme(Deep Link)启动Companion应用,但在Apple Watch上采用相同配置无法生效。
当前配置
Info.plist 注册自定义Scheme
已配置CFBundleURLTypes注册名为「Companion」的自定义scheme:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleURLTypes</key> <array> <dict> <!-- <key>CFBundleTypeRole</key> <string>Viewer</string> --> <key>CFBundleURLName</key> <string><some unique ID></string> <key>CFBundleURLSchemes</key> <array> <string>Companion</string> </array> </dict> </array> </dict> </plist>
Deep Link 处理逻辑
通过SwiftUI的onOpenURL(perform:)实现了Deep Link的接收处理:
var body: some Scene { WindowGroup { ContentView() .onOpenURL(perform: { (link: URL) in Log(String(format: "Link = %@", link.absoluteString)) // 处理Deep Link逻辑 }) } }
测试情况
iOS端:两种测试方式均有效
- 在Notes应用中输入完整Deep Link并点击;
- 开发辅助应用AppLauncher,通过按钮调用
open(_:options:completionHandler:)启动Deep Link。
Apple Watch端:测试受阻
Watch无Notes应用,尝试开发watchOS版AppLauncher时,调用的openSystemURL(_:)仅支持打开系统应用(如电话、信息),无法触发自定义scheme的应用启动。
疑问
已知watchOS支持CFBundleURLTypes、CFBundleURLSchemes等配置键,说明通过Deep Link启动Watch应用应该可行,请问还有哪些实现方法?
解决方案
1. 使用WatchKit Extension的openURL(_:options:completionHandler:)
在watchOS应用中,不要使用openSystemURL(_:),而是使用WKInterfaceController提供的openURL(_:options:completionHandler:)方法。这个方法支持打开自定义URL Scheme的应用,前提是目标应用已正确配置URL Scheme。
示例代码(在watchOS的界面控制器中):
@IBAction func launchCompanionApp() { guard let url = URL(string: "Companion://your-deep-link-path") else { return } WKInterfaceController.openURL(url) { success in if !success { // 处理打开失败的情况 } } }
2. 通过iOS应用联动启动Watch应用
如果你的iOS应用和Watch应用是配对状态,可以在iOS端触发Deep Link时,同时通过WCSession(WatchConnectivity框架)向Watch发送消息,让Watch应用启动并处理对应逻辑。
步骤:
- 确保iOS和Watch应用都开启了WatchConnectivity,并激活会话;
- iOS端打开Deep Link时,通过
WCSession.default.sendMessage(_:replyHandler:errorHandler:)向Watch发送Deep Link信息; - Watch端监听消息,在收到消息后启动对应页面或处理逻辑。
示例(iOS端):
import WatchConnectivity if WCSession.isSupported() { let session = WCSession.default session.delegate = self session.activate() } // 打开Deep Link时同时发送消息 func openCompanionDeepLink() { let deepLink = "Companion://your-path" if WCSession.default.isReachable { WCSession.default.sendMessage(["deepLink": deepLink], replyHandler: nil) { error in print("发送消息失败:\(error)") } } // 同时打开iOS端应用 if let url = URL(string: deepLink) { UIApplication.shared.open(url) } }
示例(Watch端):
import WatchConnectivity class ExtensionDelegate: NSObject, WKExtensionDelegate, WCSessionDelegate { func applicationDidFinishLaunching() { if WCSession.isSupported() { let session = WCSession.default session.delegate = self session.activate() } } func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { if let deepLink = message["deepLink"] as? String, let url = URL(string: deepLink) { // 处理Deep Link,比如导航到对应页面 WKExtension.shared().openURL(url) } } }
3. 测试时使用Xcode直接触发URL Scheme
在Xcode中运行Watch应用时,可以通过以下方式直接测试Deep Link:
- 选择Watch应用的scheme,点击「Edit Scheme」;
- 在「Run」->「Arguments」->「Arguments Passed On Launch」中添加自定义URL,比如
Companion://test-path; - 启动应用,此时应用会通过该URL启动,并触发
onOpenURL逻辑。
4. 检查Watch应用的配置细节
确保Watch应用的Info.plist配置没有遗漏:
- 确认
CFBundleURLName使用了唯一的标识符(比如反向域名格式,如com.yourcompany.companion); - 如果Watch应用是独立应用,确保配置正确;如果是依赖iOS应用的,确认iOS应用也同步配置了对应的URL Scheme;
- 检查Watch应用的权限,确保没有限制应用启动的设置。
内容的提问来源于stack exchange,提问作者NightFuryLxD

