Để thực hiện HTTP request trong iOS, dùng URLSession + URLSessionDataTask (native, không cần thư viện). Hỗ trợ GET, POST, PUT, DELETE, PATCH...
Quy trình chung (Ví dụ DELETE)
- Tạo Session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// Hoặc dùng shared session cho đơn giản: URLSession.shared
- Tạo URLRequest
let urlString = "https://api.example.com/items/123"
guard let url = URL(string: urlString) else { return }
var request = URLRequest(url: url)
request.httpMethod = "DELETE"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
// Auth header:
request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
- Tạo DataTask & Resume
let task = session.dataTask(with: request) { data, response, error in
// 1. Network error
if let error = error {
print("Network error: \(error)")
return
}
// 2. HTTP Response validation
guard let httpResponse = response as? HTTPURLResponse else {
print("Invalid response")
return
}
print("Status: \(httpResponse.statusCode)")
// 3. Handle status codes
switch httpResponse.statusCode {
case 200, 204: // 204 No Content thường dùng cho DELETE thành công
print("Xóa thành công")
DispatchQueue.main.async { /* Update UI */ }
case 400: print("Bad Request")
case 401: print("Unauthorized - token hết hạn")
case 404: print("Not Found")
case 500: print("Server Error")
default: print("Status khác: \(httpResponse.statusCode)")
}
// 4. Parse response data nếu có
if let data = data, let json = try? JSONSerialization.jsonObject(with: data) {
print("Response: \(json)")
}
}
task.resume() // BẮT BUỘC: Khởi chạy task
Hàm generic tái sử dụng (Swift 5+)
enum NetworkError: Error {
case invalidURL, invalidResponse, statusCode(Int), decoding(Error), network(Error)
}
func request(
url: String,
method: String = "GET",
headers: [String: String] = [:],
body: Data? = nil,
completion: @escaping (Result) -> Void
) {
guard let url = URL(string: url) else { completion(.failure(.invalidURL)); return }
var request = URLRequest(url: url)
request.httpMethod = method
request.httpBody = body
headers.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) }
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error { completion(.failure(.network(error))); return }
guard let httpResponse = response as? HTTPURLResponse else {
completion(.failure(.invalidResponse)); return
}
guard (200...299).contains(httpResponse.statusCode) else {
completion(.failure(.statusCode(httpResponse.statusCode))); return
}
guard let data = data else { completion(.failure(.invalidResponse)); return }
do {
let decoded = try JSONDecoder().decode(T.self, from: data)
completion(.success(decoded))
} catch {
completion(.failure(.decoding(error)))
}
}.resume()
}
// Sử dụng:
struct User: Decodable { let id: Int; let name: String }
request(url: "https://api.example.com/user/1", method: "GET") { (result: Result) in
switch result {
case .success(let user): print("User: \(user.name)")
case .failure(let err): print("Error: \(err)")
}
}
Lưu ý quan trọng
- ATS (App Transport Security): Info.plist
NSAppTransportSecuritycho HTTP hoặc domain exception. - Main Thread: Cập nhật UI trong completion phải
DispatchQueue.main.async. - Cancel: Giữ reference
taskđểtask.cancel()khi cần (ví dụ: user thoát màn hình). - Thư viện production: Alamofire (wrapper đẹp), Moya (type-safe, testable), Apollo (GraphQL).