Episode ini membahas networking di Swift: membuat HTTP request dengan URLSession, parsing respons JSON memakai Codable lengkap dengan penanganan error, penggunaan async/await untuk kode yang bersih, serta praktik terbaik seperti caching, retries, dan request timeout.

Aplikasi modern jarang berdiri sendiri — mereka berkomunikasi dengan server untuk mengambil data, mengirim input, dan menjaga state tersinkronisasi. Episode 8 membahas networking dan API integration di Swift: dari HTTP request dengan URLSession, parsing JSON dengan Codable, sampai modern concurrency dengan async/await.
Di akhir episode ini kalian akan membangun klien API yang aman, dapat diuji, dan siap produksi — termasuk penanganan error, timeout, dan retry. Networking adalah topik di mana kualitas kecil seperti penanganan error yang rapi membuat perbedaan besar di aplikasi riil.
URLSession adalah fondasi networking di platform Apple. Kombinasinya dengan async/await membuatnya sangat ringkas:
import Foundation
let url = URL(string: "https://api.github.com/users/arman")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Accept")
let (data, response) = try await URLSession.shared.data(for: request)
print("Bytes diterima: \(data.count)")try await URLSession.shared.data(for: request) menangguhkan fungsi sampai respons tiba, tanpa memblokir thread. URLSession.shared adalah sesi default yang cukup untuk sebagian besar kebutuhan; sesi custom dengan configuration akan kita bangun untuk caching dan timeout di bawah.
URLResponse harus diperiksa — sukses transfer data tidak berarti sukses HTTP. Pola yang disarankan: konversi ke HTTPURLResponse dan periksa status code:
guard let http = response as? HTTPURLResponse,
(200..<300).contains(http.statusCode) else {
throw ErrorJaringan.statusBuruk(code: (response as? HTTPURLResponse)?.statusCode ?? -1)
}
print("Status OK: \(http.statusCode)")Pola guard ... else { throw ... } memisahkan jalur error lebih awal sehingga fungsi tetap pendek dan jelas. Tangani 4xx sebagai error dari sisi client dan 5xx sebagai kegagalan server — keduanya butuh respons berbeda.
Data JSON mentah tidak berguna sampai dipetakan ke tipe Swift. Episode 7 memperkenalkan Codable; sekarang kita terapkan untuk respons API:
struct Pengguna: Codable {
let login: String
let name: String
let publicRepos: Int
enum CodingKeys: String, CodingKey {
case login
case name
case publicRepos = "public_repos"
}
}
let pengguna = try JSONDecoder().decode(Pengguna.self, from: data)
print(pengguna.login)try JSONDecoder().decode(Pengguna.self, from: data) mengubah Data menjadi instance Pengguna, membuang error decoding jika struktur tidak cocok. Gunakan CodingKeys untuk menyesuaikan snake_case dari API dengan camelCase Swift.
Gabungkan seluruh proses menjadi satu fungsi yang mengembalikan nilai atau error:
func ambilPengguna(login: String) async throws -> Pengguna {
let url = URL(string: "https://api.github.com/users/\(login)")!
let (data, response) = try await URLSession.shared.data(from: url)
guard let http = response as? HTTPURLResponse else {
throw ErrorJaringan.tidakAdaKoneksi
}
guard (200..<300).contains(http.statusCode) else {
throw ErrorJaringan.statusBuruk(code: http.statusCode)
}
return try JSONDecoder().decode(Pengguna.self, from: data)
}func ambilPengguna(login: String) async throws -> Pengguna menangkap semua kemungkinan kegagalan: jaringan, status HTTP, dan decoding. Pemanggil cukup menulis do-catch satu tingkat — pola yang menjaga pemanggil tetap sederhana.
Untuk aplikasi produksi, konfigurasikan sesi secara eksplisit alih-alih memakai shared session:
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 30
config.timeoutIntervalForResource = 60
config.waitsForConnectivity = true
config.urlCache = URLCache(memoryCapacity: 20_000_000,
diskCapacity: 50_000_000)
let session = URLSession(configuration: config)config.timeoutIntervalForRequest = 30 membatasi waktu menunggu respons per request. waitsForConnectivity = true membuat sesi menunggu jaringan pulih alih-alih langsung gagal. Sesi dengan konfigurasi ini layak dibagikan sebagai singleton di aplikasi.
URLSession mengintegrasikan URLCache secara transparan dengan header HTTP seperti Cache-Control. Untuk data yang jarang berubah, kombinasikan dengan policy:
curl -sI https://api.github.com/users/arman | grep -i cache-controlcurl -sI ... | grep -i cache-control menampilkan direktif cache yang dikirim server. Hormati direktif ini — memaksa respons caching tanpa memperhatikan header server dapat menyajikan data basi.
Jaringan tidak selalu stabil. Retry sederhana dengan jeda bertingkat memperbaiki ketahanan tanpa membebani server:
func cobaUlang<T>(_ operasi: () async throws -> T) async throws -> T {
var penundaan: UInt64 = 500_000_000
for _ in 0..<3 {
do {
return try await operasi()
} catch {
try await Task.sleep(nanoseconds: penundaan)
penundaan *= 2
}
}
return try await operasi()
}try await Task.sleep(nanoseconds: penundaan) menjeda eksekusi tanpa memblokir thread. cobaUlang menunda ulang permintaan dengan jeda 0,5 lalu 1 detik, maksimal tiga percobaan. Batasi jumlah retry — retry yang tak terkendali hanya menambah beban saat server sedang kewalahan.
Warning
Jangan pernah memakai ! untuk membuka paksa URL yang dibangun dari input pengguna. Gunakan validasi dan fallback yang aman; URL yang gagal dibentuk sebaiknya menjadi error, bukan crash.
Inti yang harus dibawa pulang:
Di episode 9 selanjutnya kita akan membahas concurrency dan async programming — Grand Central Dispatch dengan DispatchQueue, structured concurrency dengan async/await, actors, tasks, dan task groups, serta cara menghindari race condition dan menjamin thread safety lewat data isolation. Siapkan pemahaman kalian tentang threading!