Swift中URLSession无法正常工作,请求排查问题原因
Swift CLI调用OpenAI API时闭包未执行的问题解决
你的代码里闭包没被调用的核心原因是CLI程序主线程在异步网络任务完成前就退出了。URLSession.dataTask是异步执行的,调用resume()后主线程会继续执行后续打印语句,然后直接结束进程,导致异步任务的回调闭包根本没机会执行。
方案1:使用信号量阻塞主线程等待任务完成
通过信号量让主线程保持活跃,直到网络任务完成:
import Foundation let oai_key = "你的OpenAI密钥" // 替换为实际密钥 let endpoint = "https://api.openai.com/v1/completions" let headers = [ "Content-Type": "application/json", "Authorization": "Bearer \(oai_key)" ] let prompt = "Create a simple function in Swift that adds two numbers." let parameters = [ "model": "text-curie-001", "prompt": prompt, "max_tokens": 500, "temperature": 0.5, "n": 1 ] as [String: Any] guard let urlObject = URL(string: endpoint) else { print("无效的URL") exit(1) } var request = URLRequest(url: urlObject) request.httpMethod = "POST" request.allHTTPHeaderFields = headers do { request.httpBody = try JSONSerialization.data(withJSONObject: parameters) } catch { print("序列化参数失败:\(error)") exit(1) } func processResponseData(_ data: Data) { if let responseString = String(data: data, encoding: .utf8) { print("响应内容:\n\(responseString)") } else { print("无法解析响应数据") } } // 创建信号量,初始值为0,用于等待任务完成 let semaphore = DispatchSemaphore(value: 0) let newTask = URLSession.shared.dataTask(with: request) { data, response, error in defer { semaphore.signal() } // 任务完成后发送信号 print("Completion handler closure called") if let error = error { print("请求错误:\(error)") return } guard let data = data else { print("未获取到响应数据") return } processResponseData(data) } print(newTask.state) newTask.resume() print(newTask.state) // 阻塞主线程,等待信号量 semaphore.wait() print("\n任务完成")
方案2:使用Swift 5.5+的async/await(推荐)
如果你的Swift版本在5.5及以上,用async/await可以更简洁地处理异步任务,无需手动管理信号量:
import Foundation let oai_key = "你的OpenAI密钥" // 替换为实际密钥 let endpoint = "https://api.openai.com/v1/completions" func fetchOpenAIResponse() async throws -> String { let headers = [ "Content-Type": "application/json", "Authorization": "Bearer \(oai_key)" ] let prompt = "Create a simple function in Swift that adds two numbers." let parameters = [ "model": "text-curie-001", "prompt": prompt, "max_tokens": 500, "temperature": 0.5, "n": 1 ] as [String: Any] guard let url = URL(string: endpoint) else { throw NSError(domain: "InvalidURL", code: -1, userInfo: nil) } var request = URLRequest(url: url) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = try JSONSerialization.data(withJSONObject: parameters) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { throw NSError(domain: "HTTPError", code: (response as? HTTPURLResponse)?.statusCode ?? -1, userInfo: nil) } guard let responseString = String(data: data, encoding: .utf8) else { throw NSError(domain: "DataParsingError", code: -1, userInfo: nil) } return responseString } // CLI程序中通过Task调用异步函数 Task { do { let response = try await fetchOpenAIResponse() print("响应内容:\n\(response)") } catch { print("请求失败:\(error)") } exit(0) // 任务完成后退出程序 } // 启动RunLoop保持主线程活跃 RunLoop.main.run()
注意事项
- 务必替换代码中的
oai_key为你的实际OpenAI API密钥 - 方案2需要Swift 5.5及以上版本支持
- 生产环境建议补充更多错误处理逻辑(比如HTTP状态码校验、参数合法性检查等)
内容的提问来源于stack exchange,提问作者industriaditat
相关产品推荐
相关产品推荐

