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

Swift中如何让POST请求函数返回API响应字符串?

问题:让Swift的getPost函数返回POST请求的响应字符串

各位开发者好,我正在调用Rest API获取数据,目前已成功实现数据获取,但希望让getPost函数返回获取到的响应字符串。以下是我目前的代码:

private func getPost(one: String, two: String, link: String) { 
    let url = URL(string: link)! 
    var request = URLRequest(url: url) 
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 
    request.httpMethod = "POST" 
    let parameters: [String: Any] = [ 
        "parent" : one, 
        "original": two 
    ] 
    request.httpBody = parameters.percentEncoded() 
    var responseString = "" 
    print("Sarcasm \(yourMessage) \(otherMessage) \(link)") 
    let task = URLSession.shared.dataTask(with: request) { data, response, error in 
        guard let data = data, let response = response as? HTTPURLResponse, error == nil else { 
            // check for fundamental networking error 
            print("error", error ?? "Unknown error") 
            return 
        } 
        guard (200 ... 299) ~= response.statusCode else { 
            // check for http errors 
            print("statusCode should be 2xx, but is \(response.statusCode)") 
            print("response = \(response)") 
            return 
        } 
        responseString = String(data: data, encoding: .utf8)! 
        print("responseString = \(responseString)") 
        // return responseString 
    } 
    task.resume() 
} 

相关扩展代码:

extension Dictionary { 
    func percentEncoded() -> Data? { 
        return map { key, value in 
            let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? "" 
            let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? "" 
            return escapedKey + "=" + escapedValue 
        } 
        .joined(separator: "&") 
        .data(using: .utf8) 
    } 
} 
extension CharacterSet { 
    static let urlQueryValueAllowed: CharacterSet = { 
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 
        let subDelimitersToEncode = "!$&'()*+,;=" 
        var allowed = CharacterSet.urlQueryAllowed 
        allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)") 
        return allowed 
    }() 
}

我需要修改该函数,使其返回从POST请求中获取的响应字符串,而非仅打印它,但不知该如何操作。


解决方案

首先得明确:URLSession.dataTask是异步操作——函数会在网络请求完成前就执行完毕并返回,所以你不能直接用return语句返回响应字符串。我们需要用异步的方式传递结果,下面提供两种常用的可行方案:

方案1:使用闭包回调(兼容所有Swift版本)

修改函数,添加一个闭包参数来传递请求结果(成功的响应字符串或错误信息),这样就能在请求完成后拿到数据:

private func getPost(one: String, two: String, link: String, completion: @escaping (Result<String, Error>) -> Void) { 
    // 替换强制解包,避免崩溃
    guard let url = URL(string: link) else {
        completion(.failure(NSError(domain: "Invalid URL", code: -1, userInfo: nil)))
        return
    }
    
    var request = URLRequest(url: url) 
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 
    request.httpMethod = "POST" 
    
    let parameters: [String: Any] = [ 
        "parent" : one, 
        "original": two 
    ] 
    request.httpBody = parameters.percentEncoded() 
    
    print("Sarcasm \(yourMessage) \(otherMessage) \(link)") 
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in 
        // 先处理网络层面的错误
        if let error = error {
            completion(.failure(error))
            return
        }
        
        // 验证HTTP响应状态码
        guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
            let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
            let error = NSError(domain: "HTTP Error", code: statusCode, userInfo: ["response": response ?? "No response"])
            completion(.failure(error))
            return
        }
        
        // 解析响应数据为字符串
        guard let data = data, let responseString = String(data: data, encoding: .utf8) else {
            completion(.failure(NSError(domain: "Invalid Response Data", code: -2, userInfo: nil)))
            return
        }
        
        print("responseString = \(responseString)")
        completion(.success(responseString))
    } 
    task.resume() 
}

使用方式:

getPost(one: "yourValue1", two: "yourValue2", link: "yourAPIUrl") { result in
    switch result {
    case .success(let responseString):
        // 在这里处理成功获取到的响应字符串
        print("Received response: \(responseString)")
    case .failure(let error):
        // 处理请求过程中出现的错误
        print("Request failed with error: \(error.localizedDescription)")
    }
}

方案2:使用Async/Await(Swift 5.5+,iOS 15+/macOS 12+)

如果你的项目支持Swift 5.5及以上版本,用async/await会让代码更简洁易读,这也是苹果推荐的现代异步编程方式:

private func getPost(one: String, two: String, link: String) async throws -> String { 
    guard let url = URL(string: link) else {
        throw NSError(domain: "Invalid URL", code: -1, userInfo: nil)
    }
    
    var request = URLRequest(url: url) 
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 
    request.httpMethod = "POST" 
    
    let parameters: [String: Any] = [ 
        "parent" : one, 
        "original": two 
    ] 
    request.httpBody = parameters.percentEncoded() 
    
    print("Sarcasm \(yourMessage) \(otherMessage) \(link)") 
    
    // 使用async/await版本的dataTask API
    let (data, response) = try await URLSession.shared.data(for: request)
    
    // 验证HTTP状态码
    guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
        let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
        throw NSError(domain: "HTTP Error", code: statusCode, userInfo: ["response": response])
    }
    
    // 解析响应字符串
    guard let responseString = String(data: data, encoding: .utf8) else {
        throw NSError(domain: "Invalid Response Data", code: -2, userInfo: nil)
    }
    
    print("responseString = \(responseString)")
    return responseString
}

使用方式:

Task {
    do {
        let responseString = try await getPost(one: "yourValue1", two: "yourValue2", link: "yourAPIUrl")
        // 处理成功获取的响应字符串
        print("Received response: \(responseString)")
    } catch {
        // 处理请求错误
        print("Request failed with error: \(error.localizedDescription)")
    }
}

关键说明

  • 异步操作无法同步返回结果,必须通过回调或异步函数的方式传递数据
  • 两种方案都补充了完整的错误处理逻辑(比如无效URL、网络错误、非2xx状态码、数据解析失败),比原代码更健壮
  • 原代码中URL(string: link)!的强制解包存在崩溃风险,方案中改成了安全的可选绑定并抛出错误

内容的提问来源于stack exchange,提问作者Vaibhav Agrawal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:36:57