WKWebView无法加载通过DeepLink获取的动态URL问题求助
问题分析与解决方案
WebKitErrorDomain 错误码101本质是URL无法被正确解析或导航被终止,你的问题出在DeepLink的URL处理逻辑上——直接用components(separatedBy:)分割字符串的方式存在诸多隐患,容易导致最终的URL格式无效。
核心问题点
- 字符串分割的不可靠性:如果DeepLink的URL中意外包含多个
sports://(虽然概率低),last会取到错误的片段; - 缺少协议前缀:如果你的DeepLink格式是
sports://example.com/path,分割后得到的example.com/path没有http/https前缀,WebKit无法识别为合法的网络URL; - 未处理URL编码:DeepLink传递的URL可能经过百分编码(比如
sports://https%3A%2F%2Fexample.com),直接分割后未解码会导致URL格式错误。
修正后的代码
SceneDelegate 中的DeepLink处理逻辑
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let deepLinkUrl = URLContexts.first?.url else { return } // 移除自定义scheme前缀 var targetUrlString = deepLinkUrl.absoluteString.replacingOccurrences(of: "sports://", with: "") // 补全HTTP/HTTPS协议前缀(根据你的DeepLink格式调整) if !targetUrlString.hasPrefix("http://") && !targetUrlString.hasPrefix("https://") { targetUrlString = "https://" + targetUrlString } // 对编码后的字符串进行解码 let finalUrlString = targetUrlString.removingPercentEncoding ?? targetUrlString // 推荐:将URL作为通知参数传递,避免全局变量 NotificationCenter.default.post( name: NSNotification.Name(rawValue: "deepLink"), object: finalUrlString ) }
ViewController 中的URL加载逻辑
// 注册通知时(建议在viewDidLoad中) override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(handleDeepLink(_:)), name: NSNotification.Name(rawValue: "deepLink"), object: nil ) } @objc private func handleDeepLink(_ notification: NSNotification) { guard let urlString = notification.object as? String, let targetUrl = URL(string: urlString) else { print("无效的DeepLink URL") return } let request = URLRequest(url: targetUrl) webView.load(request) } // 记得在deinit中移除通知监听 deinit { NotificationCenter.default.removeObserver(self) }
额外优化建议
- 避免全局变量:全局变量
g_url容易引发状态混乱,直接将URL作为通知的object传递更安全; - 添加错误日志:在URL解析失败时打印日志,方便排查问题;
- 使用URLComponents解析:如果你的DeepLink有复杂参数(比如
sports://example.com/path?param=1),用URLComponents解析会更严谨:if let components = URLComponents(url: deepLinkUrl, resolvingAgainstBaseURL: false), let host = components.host, let path = components.path { let targetUrlString = "https://\(host)\(path)\(components.query ?? "")" // ...后续处理 }
内容的提问来源于stack exchange,提问作者Baeta
相关产品推荐
相关产品推荐

