Unowned Reference: apa itu, sintaksis dan penerapan di aplikasi mobile

Penulis: IT Sectr Diterbitkan: 2026-03-30 Waktu membaca: 9 mnt

Unowned Reference (referensi tanpa pemilik) — adalah referensi tidak memiliki di Swift yang tidak meningkatkan retain count objek dan, tidak seperti weak, tidak diset ke nil setelah pembebasannya. Menurut Apple Swift Language Guide, 2026, unowned diterapkan ketika dijamin bahwa objek hidup setidaknya selama objek yang merujuk padanya. Berbeda dengan Weak Reference, unowned tidak memerlukan unwrap — ini adalah tipe non-optional, yang membuat kode lebih bersih, tetapi menempatkan tanggung jawab jaminan masa hidup pada pengembang.

Poin Utama

  • Unowned Reference — referensi tanpa pemilik tanpa zeroing otomatis; non-optional, tidak meningkatkan retain count
  • Jaminan — diterapkan ketika objek dijamin tidak dapat dibebaskan sebelum objek yang merujuk
  • Perbedaan dari weak — unowned tidak di-nol-kan ke nil (risiko crash), weak di-nol-kan (aman)
  • Skenario — parent-child dengan jaminan hidup, closure dengan unowned self, singleton dan Service Locator
  • Risiko — akses ke objek unowned yang dibebaskan menyebabkan runtime crash (EXC_BAD_ACCESS)

Apa itu Unowned Reference?

Unowned Reference — adalah referensi tidak memiliki ke objek di ARC yang tidak meningkatkan retain count-nya. Tidak seperti weak, unowned tidak di-nol-kan setelah dealokasi objek: ia terus menunjuk ke area memori yang sudah dibebaskan. Akses ke referensi semacam itu menyebabkan runtime crash dengan EXC_BAD_ACCESS.

Istilah “tanpa pemilik” mencerminkan semantik: objek ada, tetapi tidak ada yang bertanggung jawab atas masa hidupnya. Pengembang secara eksplisit menyatakan: “saya jamin bahwa objek ini akan hidup selama saya merujuknya”. Kompilator tidak memeriksa jaminan ini — ini adalah kontrak di tingkat pengembang.

Menurut Swift.org Documentation, 2026, referensi unowned lebih diutamakan daripada weak dalam skenario dengan masa hidup terjamin karena: tidak memerlukan tipe opsional (kode lebih bersih), tidak memerlukan unwrap (lebih sedikit force-unwrap atau guard let), dan tidak memiliki overhead untuk memelihara tabel weak zeroing. Namun, setiap pelanggaran kontrak — crash.

Sintaksis unowned di Swift

Di Swift, referensi unowned dideklarasikan dengan kata kunci unowned sebelum let atau var. Tidak seperti weak, unowned bisa baik let maupun var dan tidak memerlukan tipe opsional. Properti ini membuat unowned nyaman untuk referensi yang tidak bisa nil menurut logika domain.

swift
class Country {
    let name: String
    var capital: City!           // akan diatur setelah inisialisasi
    init(name: String) { self.name = name }
}

class City {
    let name: String
    unowned let country: Country   // unowned let — jaminan hidup

    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}

// Penggunaan
let france = Country(name: "France")
let paris = City(name: "Paris", country: france)
france.capital = paris
// Country → City (strong), City → Country (unowned) — tidak ada retain cycle

Dalam contoh ini City unowned let country — kota tidak dapat ada tanpa negara. Jika negara menghilang, kota (dan referensi) kehilangan makna. Secara semantik, ini adalah kasus ideal untuk unowned: jaminan masa hidup ada, optional tidak diperlukan, retain cycle tidak terjadi.

unowned var

unowned var diizinkan tetapi lebih jarang ditemui. Digunakan ketika referensi dapat diganti (misalnya, menghubungkan ulang anak ke orang tua lain). Saat penggantian, pembebasan objek lama — tanggung jawab pemilik eksternal.

Unowned Optional

Di Swift 5.0+ dukungan untuk unowned optional ditambahkan (unowned let x: Type?). Ini adalah kompromi: unowned menjamin bahwa jika referensi tidak nil, objek hidup. Perilaku saat pembebasan — crash, seperti unowned biasa.

Unowned vs Weak: kapan menggunakan apa

Pilihan antara unowned dan weak — salah satu keputusan sering dalam merancang arsitektur Swift. Mari kita lihat kriteria dan rekomendasi untuk setiap kasus.

KriteriaWeakUnowned
OptionalYa (Type?)Tidak (Type)
Zeroing saat dealokasiOtomatis ke nilTidak (risiko pointer menggantung)
Tipe (let/var)Hanya varlet atau var
KinerjaOverhead untuk tabel weakMinimal (pointer sederhana)
KeamananAman (nil diperiksa)Risiko EXC_BAD_ACCESS
Jaminan masa hidupTidak diperlukanJaminan eksplisit diperlukan

Aturan praktis

Gunakan weak jika ada sedikit pun keraguan tentang masa hidup objek. Weak aman, mudah dipahami, dan tidak memerlukan bukti. Gunakan unowned hanya ketika Anda telah mengecualikan semua skenario di mana objek dapat dibebaskan lebih awal. Kasus tipikal: anak yang tidak ada tanpa orang tua; closure yang dijalankan secara sinkron; merujuk ke objek dalam inisialisasinya.

Menurut Airbnb Swift Style Guide, 2025, di basis kode besar direkomendasikan menggunakan weak secara default dan unowned — hanya dengan komentar eksplisit yang menjelaskan jaminan masa hidup. Ini mengurangi risiko crash tak terduga saat refactoring.

Unowned self di closure

Closure — skenario penggunaan unowned kedua paling sering setelah hubungan parent-child. Capture list [unowned self] diterapkan ketika self dijamin hidup lebih lama dari closure. Mari kita lihat skenario benar dan salah.

Kapan unowned self aman

Closure sinkron — sorted, filter, map. Mereka segera dijalankan di thread saat ini, self pasti hidup. Capture list dengan unowned di sini dapat diterima dan memberikan kode lebih bersih.

swift
class DataProcessor {
    var items: [Int] = [3, 1, 4, 1, 5]

    func processSorted() {
        // unowned self — sorted dieksekusi sinkron, self dijamin hidup
        let sorted = items.sorted { [unowned self] a, b in
            return self.customCompare(a, b)
        }
    }

    func customCompare(_ a: Int, _ b: Int) -> Bool { return a < b }
}

Kapan unowned self berbahaya

Closure asinkron — dengan penundaan, permintaan jaringan, animasi. Self dapat dibebaskan antara penempatan closure dan eksekusinya. Di sini unowned self → crash. Gunakan [weak self].

swift
class NetworkLoader {
    func loadData() {
        // BERBAHAYA: unowned self di closure asinkron
        URLSession.shared.dataTask(with: url) { [unowned self] data, _, _ in
            self.handleResponse(data)  // CRASH jika self telah dibebaskan
        }.resume()
    }

    func handleResponse(_ data: Data?) { }

    // BENAR: weak self + guard
    func loadDataSafe() {
        URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
            guard let self else { return }
            self.handleResponse(data)
        }.resume()
    }
}

Ingat aturannya: unowned self — hanya untuk closure sinkron yang dijalankan segera. Untuk asinkron — selalu weak self + guard let. Pengecualian: jika Anda secara eksplisit memegang referensi ke objek sampai closure selesai (misalnya, dengan menyimpan capture kuat di variabel lain).

Risiko unowned dan cara menghindarinya

Unowned — alat yang kuat tetapi berbahaya. Mari kita lihat skenario nyata di mana unowned dapat menyebabkan crash dan metode minimisasi risiko.

Refactoring dan perubahan jaminan

Risiko utama unowned — perubahan logika bisnis yang menyebabkan jaminan masa hidup tidak lagi terpenuhi. Pengembang merefaktor kode: mengubah kepemilikan, memperkenalkan pembebasan tertunda, menambahkan caching — dan referensi unowned berubah menjadi bom waktu. Kompilator tidak akan memperingatkan — hanya crash di perangkat pengguna.

Rekomendasi: gunakan unowned hanya ketika jaminan masa hidup jelas dan terdokumentasi. Tambahkan komentar ke setiap unowned: mengapa referensi ini aman dan dalam kondisi apa dapat dilanggar.

Unowned di hierarki UIKit

UIKit — zona risiko tinggi untuk unowned. ViewController dapat dibebaskan kapan saja saat navigasi (pop, dismiss), pembongkaran dari memori, perubahan orientasi. Jika Anda meneruskan ViewController ke closure dengan unowned self — saat kembali dari latar belakang atau akhir animasi, self bisa nil.

Praktik terbaik

Untuk mengurangi risiko saat menggunakan unowned, ikuti aturan ini:

  • Pilih weak secara default — weak aman, unowned adalah optimasi, bukan standar
  • Dokumentasikan jaminan — untuk setiap unowned tulis komentar dengan justifikasi
  • Hindari unowned di ViewController — siklus hidup UIKit tidak dapat diprediksi untuk jaminan unowned
  • Gunakan unowned hanya untuk closure sinkron — sorted, filter, map — kandidat aman
  • Periksa saat code review — setiap unowned memerlukan justifikasi dari penulis kode
  • Migrasi ke weak saat keraguan sekecil apa pun — kehilangan keterbacaan (satu guard let) lebih kecil dari crash di produksi
swift
// Contoh: referensi unowned terdokumentasi dengan justifikasi eksplisit
class InvoiceLineItem {
    let productName: String
    let price: Decimal

    // unowned Invoice — InvoiceLineItem tidak bisa ada tanpa Invoice.
    // Invoice membuat Item dan menghapusnya saat penghapusan dirinya.
    // Jaminan: Invoice hidup setidaknya selama Item.
    unowned let invoice: Invoice

    init(productName: String, price: Decimal, invoice: Invoice) {
        self.productName = productName
        self.price = price
        self.invoice = invoice
    }
}

// Ini jaminan kuat: Invoice menghapus semua Item di deinit.
// pelanggaran jaminan = bug dalam logika bisnis yang perlu diperbaiki.

Dokumentasi jaminan — standar profesional. Di proyek besar (Airbnb, Uber) code review memerlukan justifikasi setiap unowned. Jika jaminan tidak jelas — gunakan weak. Komentar pada unowned membantu pengembang masa depan memahami mengapa di sini tidak ada weak dan kondisi apa yang dapat merusak jaminan.

Pertanyaan Umum

Apa yang terjadi saat mengakses referensi unowned setelah objek dibebaskan?

Runtime crash dengan EXC_BAD_ACCESS. Swift tidak memeriksa validitas referensi unowned saat akses — ini hanya pointer “mentah”. Jika objek telah dibebaskan, memori ditimpa dan akses ke sana berakhir dengan crash. Ini adalah pengecualian tidak tertangkap (bukan try-catch).

Bisakah unowned digunakan dengan protokol?

Ya, jika protokol mewarisi dari AnyObject. Unowned bekerja dengan semua tipe referensi: kelas, protokol AnyObject, objek Objective-C. Tipe nilai (struct, enum) tidak mendukung unowned karena tidak berpartisipasi dalam ARC.

Kapan unowned lebih aman daripada weak?

Ketika jaminan masa hidup absolut dan jelas — unowned lebih aman dari segi desain: tidak memerlukan unwrap, tidak bisa nil, tidak menyembunyikan kesalahan. Jika objek tidak dapat ada tanpa orang tua, unowned menjadikannya kontrak eksplisit, sedangkan weak mengaburkan jaminan.

Apakah ada perbedaan kinerja antara unowned dan weak?

Ya: unowned lebih cepat karena tidak memerlukan akses ke tabel weak runtime untuk zeroing. Di kebanyakan aplikasi perbedaannya tidak terasa, tetapi dalam skenario beban tinggi dengan jutaan akses, unowned bisa 10–20% lebih cepat saat membaca.

Bagaimana refactoring mempengaruhi jaminan unowned?

Refactoring — bahaya utama bagi unowned. Perubahan masa hidup objek (caching, operasi asinkron, penggunaan ulang) dapat melanggar jaminan. Kompilator tidak akan memperingatkan. Solusi: migrasi ke weak saat perubahan arsitektur atau tambahkan komentar peringatan.

Ringkasan

  • Unowned Reference — referensi tanpa pemilik tanpa zeroing; non-optional, tidak meningkatkan retain count
  • Jaminan — memerlukan bukti eksplisit bahwa objek hidup setidaknya selama kode yang merujuknya
  • Sintaksisunowned let atau unowned var; bisa non-optional dan optional (Swift 5.0+)
  • Unowned vs Weak — unowned lebih cepat dan bersih, tetapi weak lebih aman; weak — pilihan default
  • Closure — unowned self hanya untuk closure sinkron; asinkron memerlukan [weak self]
  • Dokumentasi — setiap unowned harus memiliki komentar dengan justifikasi jaminan
  • Rekomendasi — saat ragu pilih weak; unowned — untuk kontrak eksplisit dan terdokumentasi

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga