You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:17:40