Swift调用Spotify API时URLSession报nw_connection未连接错误原因
问题原因
- API路径拼写错误:Spotify 单曲目查询的官方API路径为
/v1/tracks/{id},你代码中写的/v1/track/缺少末尾的s,错误路径会触发服务端404响应,异常响应场景可能触发URLSession底层网络栈报错,对应你看到的nw_connection系列日志。 - URL构造存在安全隐患:你直接通过字符串插值拼接ID,没有做URL百分号编码。如果ID中包含空格、特殊符号等不符合URL规范的字符,
URL(string:)会返回nil,你使用!强制解包会直接触发致命崩溃。而else分支使用URLComponents构造URL,会自动处理参数编码,因此不会出现这类问题。 - 可选值判断不严谨:你用
if (id != nil)判断后强制解包id!,在多线程场景下可能出现判断完成后id被其他线程置为nil的情况,同样会触发解包崩溃,这类崩溃属于runtime致命错误,无法被do-catch捕获。
修复方案
// 定义自定义错误类型 enum NetworkError: Error { case invalidURL case invalidResponse } // 重构请求构造逻辑 var request: URLRequest // 用可选绑定替代非空判断+强制解包 if let id = id { // 对路径参数做百分号编码,避免非法字符导致URL构造失败 guard let encodedId = id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed), let url = URL(string: "https://api.spotify.com/v1/tracks/\(encodedId)") else { throw NetworkError.invalidURL } request = URLRequest(url: url) } else { var url = URLComponents(string: "https://api.spotify.com/v1/search")! url.queryItems = [ URLQueryItem(name: "q", value: self.queryString), URLQueryItem(name: "type", value: self.typeString) ] guard let searchUrl = url.url else { throw NetworkError.invalidURL } request = URLRequest(url: searchUrl) } request.httpMethod = "GET" request.addValue("Bearer \(self.qe.accessToken!)", forHTTPHeaderField: "Authorization") let (data, response) = try await URLSession.shared.data(for: request) // 增加响应状态码校验,避免异常响应后续解析崩溃 guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { throw NetworkError.invalidResponse }
调试建议
- 加断点定位崩溃位置:打开Xcode左侧断点导航,点击左下角+号,分别添加「Swift Error Breakpoint」和「Exception Breakpoint」,所有runtime崩溃都会触发断点停在崩溃行,可直接区分是URL构造阶段解包失败,还是请求阶段异常。
- 打印请求全量信息:在发起请求前打印
request.url?.absoluteString,确认if分支拼接的URL是否符合预期,有没有拼写错误、特殊字符未编码的问题。 - 用系统工具调试网络:运行App后打开Xcode左侧「Debug Navigator」,选择「Network」选项,可看到所有网络请求的URL、状态码、响应头/响应体,直接确认请求是否正确发送、服务端返回内容是否符合预期。
- 避免滥用强制解包:所有可能返回nil的系统API(URL构造、类型转换、可选值取值)都用
if let/guard let做可选绑定,从根源避免无法被do-catch捕获的致命错误。
内容的提问来源于stack exchange,提问作者kawub
相关产品推荐
相关产品推荐

