Belajar Swift - Networking & API Integration
Episode 8 of 23

Belajar Swift - Networking & API Integration

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.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

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 dan HTTP Request

Membuat Request Dasar

URLSession adalah fondasi networking di platform Apple. Kombinasinya dengan async/await membuatnya sangat ringkas:

Request GET dengan async/await
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.

Memeriksa Status Respons

URLResponse harus diperiksa — sukses transfer data tidak berarti sukses HTTP. Pola yang disarankan: konversi ke HTTPURLResponse dan periksa status code:

Memvalidasi 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.

Parsing JSON dengan Codable

Model dan Decoder

Data JSON mentah tidak berguna sampai dipetakan ke tipe Swift. Episode 7 memperkenalkan Codable; sekarang kita terapkan untuk respons API:

Mendekode JSON respons
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.

Error Handling Respons

Gabungkan seluruh proses menjadi satu fungsi yang mengembalikan nilai atau error:

Fungsi fetch lengkap
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.

Konfigurasi Sesi dan Timeout

URLSessionConfiguration

Untuk aplikasi produksi, konfigurasikan sesi secara eksplisit alih-alih memakai shared session:

Sesi dengan timeout
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.

Caching dan Retries

Strategi Cache

URLSession mengintegrasikan URLCache secara transparan dengan header HTTP seperti Cache-Control. Untuk data yang jarang berubah, kombinasikan dengan policy:

Periksa header cache API
curl -sI https://api.github.com/users/arman | grep -i cache-control

curl -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.

Retry dengan Exponential Backoff

Jaringan tidak selalu stabil. Retry sederhana dengan jeda bertingkat memperbaiki ketahanan tanpa membebani server:

Retry dengan backoff
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.

Penutup

Inti yang harus dibawa pulang:

  • URLSession dengan async/await membuat HTTP request ringkas dan non-blocking.
  • Selalu periksa status code sebelum memproses data.
  • JSONDecoder memetakan JSON ke tipe Codable; CodingKeys menangani nama berbeda.
  • Bungkus seluruh kegagalan networking dalam satu fungsi throws.
  • Konfigurasi sesi menentukan timeout, cache, dan perilaku saat jaringan hilang.
  • Retry dengan exponential backoff meningkatkan ketahanan tanpa membebani server.

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!

Belajar Swift - Networking & API Integration | Belajar Swift