http编程
import Foundation
func getRequest(urlStr: String) {
guard let url = URL(string: urlStr) else {
print("URL 无效")
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("请求失败:\(error.localizedDescription)")
return
}
guard let data = data else {
print("无返回数据")
return
}
// 解析数据
if let str = String(data: data, encoding: .utf8) {
print("返回内容:\(str)")
}
}
task.resume()
}
// 调用
getRequest(urlStr: "https://httpbin.org/get")
// POST JSON
func postJson(urlStr: String, params: [String: Any]) {
guard let url = URL(string: urlStr) else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params)
} catch {
print("参数转JSON失败:\(error)")
return
}
URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error {
print(error)
return
}
guard let data = data else { return }
print(String(data: data, encoding: .utf8) ?? "")
}.resume()
}
// 调用
postJson(urlStr: "https://httpbin.org/post", params: ["name": "Swift", "age": 20])
async await
import Foundation
// 自定义错误
enum NetworkError: Error {
case invalidURL
case noData
case requestFailed
}
// GET 异步请求
func asyncGet(urlStr: String) async throws -> Data {
guard let url = URL(string: urlStr) else { throw NetworkError.invalidURL }
let (data, response) = try await URLSession.shared.data(from: url)
guard let httpResp = response as? HTTPURLResponse,
(200...299).contains(httpResp.statusCode) else {
throw NetworkError.requestFailed
}
return data
}
// POST JSON 异步请求
func asyncPost(urlStr: String, params: [String: Any]) async throws -> Data {
guard let url = URL(string: urlStr) else { throw NetworkError.invalidURL }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONSerialization.data(withJSONObject: params)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResp = response as? HTTPURLResponse,
(200...299).contains(httpResp.statusCode) else {
throw NetworkError.requestFailed
}
return data
}
切换回来主线程
func testAsyncHttp() {
Task {
do {
let data = try await asyncGet(urlStr: "https://httpbin.org/get")
let result = String(data: data, encoding: .utf8) ?? ""
// 切主线程更新 UI
await MainActor.run {
print("主线程收到数据:\(result.prefix(200))")
// label.text = result
}
} catch {
await MainActor.run {
print("请求异常:\(error)")
}
}
}
}
testAsyncHttp()
结合 Codable 做统一解析,一套方法支持所有接口。
import Foundation
enum NetError: Error {
case invalidURL, noData, statusError
}
// 通用请求工具
final class HttpTool {
static let shared = HttpTool()
private init() {}
/// 通用 GET 请求,自动解析 Model
func get<T: Codable>(urlStr: String) async throws -> T {
guard let url = URL(string: urlStr) else { throw NetError.invalidURL }
let (data, resp) = try await URLSession.shared.data(from: url)
try checkResponse(resp)
return try JSONDecoder().decode(T.self, from: data)
}
/// 通用 POST JSON 请求
func post<T: Codable>(urlStr: String, params: [String: Any]) async throws -> T {
guard let url = URL(string: urlStr) else { throw NetError.invalidURL }
var req = URLRequest(url: url)
req.httpMethod = "POST"
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpBody = try JSONSerialization.data(withJSONObject: params)
let (data, resp) = try await URLSession.shared.data(for: req)
try checkResponse(resp)
return try JSONDecoder().decode(T.self, from: data)
}
// 校验状态码
private func checkResponse(_ response: URLResponse) throws {
guard let httpResp = response as? HTTPURLResponse,
(200...299).contains(httpResp.statusCode) else {
throw NetError.statusError
}
}
}
// ------------------- 使用示例 -------------------
// 1. 定义数据模型
struct HttpBinModel: Codable {
let url: String
let origin: String
}
// 2. 发起请求
func requestModel() {
Task {
do {
let model: HttpBinModel = try await HttpTool.shared.get(urlStr: "https://httpbin.org/get")
await MainActor.run {
print("解析结果:\(model.url)")
}
} catch {
print("请求/解析失败:\(error)")
}
}
}
requestModel()