Swift调用API时URL(string: url)!处报EXC_BREAKPOINT错误如何解决
崩溃原因
URL(string: url)! 处的崩溃是强制解包nil可选值导致的:URL(string:)构造方法只有传入符合RFC 2396规范的字符串才会返回有效URL实例,当你传入的字符串包含未编码的中文、空格、特殊符号,或者字符串本身为空、格式错误时,该方法会返回nil,用!强制解包nil就会触发EXC_BREAKPOINT运行时崩溃。
另外Postman自动导出的代码使用DispatchSemaphore阻塞线程的写法非常不合理,如果你在主线程调用该方法会直接卡住UI,也建议一并修改。
修复方案
第一步:移除强制解包,增加安全校验
首先修改apiCall方法的URL构造逻辑,避免强制解包:
func apiCall(url: String) { let semaphore = DispatchSemaphore(value: 0) // 安全校验URL构造结果 guard let validUrl = URL(string: url) else { print("URL构造失败,传入的字符串非法:\(url)") semaphore.signal() return } var request = URLRequest(url: validUrl, timeoutInterval: Double.infinity) request.httpMethod = "GET" let task = URLSession.shared.dataTask(with: request) { data, response, error in defer { semaphore.signal() } guard let data = data, error == nil else { print("请求失败:\(String(describing: error))") return } guard let resultStr = String(data: data, encoding: .utf8) else { print("响应数据解析失败") return } print(resultStr) } task.resume() semaphore.wait() }
如果运行后控制台打印URL构造失败的日志,说明你传入的urlEncode变量本身没有做好编码处理,需要对URL的路径/参数部分提前做百分号编码:
// 示例:对包含特殊字符的字符串做URL编码 if let encodedStr = yourOriginalUrlStr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) { apiCall(url: encodedStr) }
第二步:优化不合理的信号量写法(推荐)
实际iOS开发中不要用信号量阻塞线程的方式处理异步请求,改成回调式写法更合理,不会卡住线程:
func apiCall(url: String, completion: @escaping (Result<String, Error>) -> Void) { guard let validUrl = URL(string: url) else { completion(.failure(NSError(domain: "ApiError", code: -1, userInfo: [NSLocalizedDescriptionKey: "URL格式非法"]))) return } var request = URLRequest(url: validUrl, timeoutInterval: 30) // 建议设置合理的超时时间,不要用无穷大 request.httpMethod = "GET" URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { completion(.failure(error)) return } guard let data = data, let resultStr = String(data: data, encoding: .utf8) else { completion(.failure(NSError(domain: "ApiError", code: -2, userInfo: [NSLocalizedDescriptionKey: "响应解析失败"]))) return } completion(.success(resultStr)) }.resume() } // 调用方式 apiCall(url: urlEncode) { result in DispatchQueue.main.async { // 涉及UI更新要切回主线程 switch result { case .success(let str): print("请求成功:\(str)") // 处理业务逻辑 case .failure(let error): print("请求失败:\(error.localizedDescription)") // 处理错误 } } }
内容的提问来源于stack exchange,提问作者frincit
相关产品推荐
相关产品推荐

