Swift开发中如何为URL添加http/https协议头以正常使用富链接功能
问题根因分析
- 缺双斜杠的原因:你直接对
example.com这类无协议字符串生成的URL修改scheme时,系统会把整段字符串识别为path而非host,修改scheme后生成的URL自然缺少host前的//标识。 - HTTP站点访问失败的原因:默认强制加HTTPS协议,没有兼容未部署HTTPS的老旧站点。
修复方案
第一步:修正无协议链接预处理逻辑(解决缺双斜杠问题)
优先在字符串阶段处理无协议链接,不要转成URL后再修改scheme:
// 拿到NSDataDetector匹配的urlString后先做预处理 let rawURLString = String(text[range]) let processedURLString: String if rawURLString.lowercased().hasPrefix("http://") || rawURLString.lowercased().hasPrefix("https://") { processedURLString = rawURLString } else { // 直接拼接前缀,保证生成的URL结构正确 processedURLString = "https://" + rawURLString } guard let url = URL(string: processedURLString) else { return }
如果要保留URL扩展的写法,也可以改成如下实现:
extension URL { var sanitized: URL { guard scheme == nil || !(scheme?.lowercased() == "http" || scheme?.lowercased() == "https") else { return self } return URL(string: "https://\(absoluteString)") ?? self } }
第二步:增加协议降级重试逻辑(兼容HTTP站点)
你想到的失败重试思路是行业通用的兼容方案,只需稍加优化即可落地,避免无限重试:
func fetchMetadata(for link: String, retryIfHTTPSFail: Bool = true, completion: @escaping (Result<LPLinkMetadata, Error>) -> Void) { guard let url = URL(string: link.lowercased()) else { completion(.failure(NSError(domain: "RichLinkError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效链接"]))) return } let metadataProvider = LPMetadataProvider() metadataProvider.startFetchingMetadata(for: url) { metadata, error in // HTTPS请求失败且未重试过时,降级为HTTP重试 if let error = error, retryIfHTTPSFail, url.scheme == "https" { var components = URLComponents(url: url, resolvingAgainstBaseURL: false) components?.scheme = "http" guard let httpURL = components?.url else { completion(.failure(error)) return } // 重试时关闭重试开关,避免无限循环 self.fetchMetadata(for: httpURL.absoluteString, retryIfHTTPSFail: false, completion: completion) return } if let error = error { completion(.failure(error)) return } if let metadata = metadata { completion(.success(metadata)) } } }
额外优化建议
- 如果产品规则不允许展示HTTP链接,可以关闭重试开关,直接提示用户链接无效。
- LPMetadataProvider默认有系统级缓存,重复请求同一链接不会产生多余网络开销。
- 可以根据业务需求增加超时控制,避免系统请求长时间无返回阻塞队列。
内容的提问来源于stack exchange,提问作者alionthego
相关产品推荐
相关产品推荐

