Unowned Reference (референца без власника) — је референца која не повећава retain count објекта и, за разлику од weak, не поставља се на nil након његовог ослобађања. Према Apple Swift Language Guide, 2026, unowned се примењује када је гарантовано да објекат живи барем колико и објекат који се на њега позива. За разлику од Weak Reference, unowned не захтева unwrap — то је non-optional тип, што чини код чистијим, али ставља одговорност за гаранцију животног века на програмера.
Главно
Unowned Reference — је невласничка референца на објекат у ARC-у која не повећава његов retain count. За разлику од weak, unowned се не нулира након деалокације објекта: наставља да показује на меморијску област која је већ ослобођена. Позивање на такву референцу изазива runtime crash са EXC_BAD_ACCESS.
Термин „без власника“ одражава семантику: објекат постоји, али нико не одговара за његов животни век. Програмер изричито изјављује: „гарантујем да ће овај објекат бити жив док се позивам на њега“. Компајлер не проверава ову гаранцију — то је уговор на нивоу програмера.
Према Swift.org Documentation, 2026, unowned референце су пожељније од weak у сценаријима са гарантованим животним веком, јер: не захтевају опционални тип (чистији код), не захтевају unwrap (мање force-unwrap или guard let) и немају додатне трошкове за одржавање zeroing weak-табеле. Међутим, било какво кршење уговора — crash.
У Swift-у unowned референце се декларишу кључном речју unowned испред let или var. За разлику од weak, unowned може бити и let и var и не захтева опционални тип. Ово својство чини unowned погодним за референце које не могу бити nil по логици домена.
class Country {
let name: String
var capital: City! // биће постављено након иницијализације
init(name: String) { self.name = name }
}
class City {
let name: String
unowned let country: Country // ✅ unowned let — гаранција живота
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
// Коришћење
let france = Country(name: "France")
let paris = City(name: "Paris", country: france)
france.capital = paris
// ✅ Country → City (strong), City → Country (unowned) — нема retain cycle
У овом примеру City unowned let country — град не може постојати без земље. Ако земља нестане, град (и референца) губе смисао. Семантички, ово је идеалан случај за unowned: гаранција животног века постоји, optional није потребан, retain cycle не настаје.
unowned var је дозвољено, али се ређе среће. Користи се када референца може бити замењена (нпр. превезивање детета на другог родитеља). При замени, ослобађање старог објекта — одговорност спољног власника.
У Swift 5.0+ појавила се подршка за unowned optional (unowned let x: Type?). То је компромис: unowned гарантује да ако референца није nil, објекат је жив. Понашање при ослобађању — crash, као и код обичног unowned-а.
Избор између unowned и weak — једна од честих одлука при пројектовању Swift архитектуре. Размотримо критеријуме и препоруке за сваки случај.
| Критеријум | Weak | Unowned |
|---|---|---|
| Optional | Да (Type?) | Не (Type) |
| Нулирање при деалокацији | Ауто у nil | Не (ризик од висећег показивача) |
| Тип (let/var) | Само var | let или var |
| Перформансе | Додатни трошкови за weak-табелу | Минимални (обичан показивач) |
| Безбедност | Безбедно (nil се проверава) | Ризик EXC_BAD_ACCESS |
| Гаранција животног века | Није потребна | Потребна је изричита гаранција |
Користите weak ако постоји и најмања сумња у животни век објекта. Weak је безбедан, разумљив и не захтева доказе. Користите unowned само када сте искључили све сценарије у којима објекат може бити ослобођен раније. Типични случајеви: дете које не постоји без родитеља; затварање које се извршава синхроно; позивање на објекат у оквиру његовог иницијализатора.
Према Airbnb Swift Style Guide, 2025, у великим базама кода препоручује се коришћење weak подразумевано, а unowned — само са изричитим коментаром који објашњава гаранцију животног века. Ово смањује ризик од неочигледних крашева при рефакторисању.
Затварања (closures) — други по учесталости сценариј употребе unowned-а после parent-child односа. Capture list [unowned self] примењује се када је загарантовано да self живи дуже од затварања. Размотримо исправне и неисправне сценарије.
Синхрона затварања — sorted, filter, map. Извршавају се одмах у тренутној нити, self је сигурно жив. Capture list са unowned-ом је овде прихватљив и даје чистији код.
class DataProcessor {
var items: [Int] = [3, 1, 4, 1, 5]
func processSorted() {
// ✅ unowned self — sorted се извршава синхроно, self гарантовано жив
let sorted = items.sorted { [unowned self] a, b in
return self.customCompare(a, b)
}
}
func customCompare(_ a: Int, _ b: Int) -> Bool { return a < b }
}
Асинхрона затварања — са кашњењем, мрежним захтевима, анимацијама. Self може бити ослобођен између постављања затварања и његовог извршавања. Овде unowned self → crash. Користите [weak self].
class NetworkLoader {
func loadData() {
// ❌ ОПАСНО: unowned self у асинхроном затварању
URLSession.shared.dataTask(with: url) { [unowned self] data, _, _ in
self.handleResponse(data) // CRASH ако је self ослобођен
}.resume()
}
func handleResponse(_ data: Data?) { }
// ✅ ИСПРАВНО: weak self + guard
func loadDataSafe() {
URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
guard let self else { return }
self.handleResponse(data)
}.resume()
}
}
Запамтите правило: unowned self — само за синхрона затварања која се извршавају одмах. За асинхрона — увек weak self + guard let. Изузетак: ако изричито држите референцу на објекат до завршетка затварања (нпр. чувањем снажног захвата у другој променљивој).
Unowned — моћан, али опасан алат. Размотримо реалне сценарије у којима unowned може довести до краша и методе минимизације ризика.
Главни ризик unowned-а — промена пословне логике при којој гаранција животног века престаје да важи. Програмер рефакторише код: мења власништво, уводи одложено ослобађање, додаје кеширање — и unowned референца постаје бомба са одложеним дејством. Компајлер неће упозорити — само crash на уређају корисника.
Препорука: користите unowned само када је гаранција животног века очигледна и документована. Додајте коментар уз сваки unowned: зашто је ова референца безбедна и под којим условима може бити нарушена.
UIKit — зона повишеног ризика за unowned. ViewController може бити ослобођен у било ком тренутку при навигацији (pop, dismiss), истовару из меморије, промени оријентације. Ако прослеђујете ViewController у затварање са unowned self — при повратку из позадине или завршетку анимације self може бити nil.
Да бисте смањили ризик при коришћењу unowned-а, следите ова правила:
// Пример: документована unowned референца са јасним образложењем
class InvoiceLineItem {
let productName: String
let price: Decimal
// unowned Invoice — InvoiceLineItem не може постојати без Invoice.
// Invoice креира Item и брише га при свом брисању.
// Гаранција: Invoice живи барем колико и Item.
unowned let invoice: Invoice
init(productName: String, price: Decimal, invoice: Invoice) {
self.productName = productName
self.price = price
self.invoice = invoice
}
}
// Ово је јака гаранција: Invoice брише све Item у deinit.
// кршење гаранције = грешка у пословној логици коју треба поправити.
Документовање гаранција — професионални стандард. У великим пројектима (Airbnb, Uber) code review захтева образложење сваког unowned-а. Ако гаранција није очигледна — користите weak. Коментар уз unowned помаже будућим програмерима да разумеју зашто овде нема weak-а и који услови могу нарушити гаранцију.
Често постављана питања
Runtime crash са EXC_BAD_ACCESS. Swift не проверава валидност unowned референце при приступу — то је само „сирови“ показивач. Ако је објекат ослобођен, меморија је преписана, а приступ јој се завршава крашом. Ово је неухватљив изузетак (није try-catch).
Да, ако протокол наслеђује од AnyObject. Unowned ради са свим референцним типовима: класе, AnyObject протоколи, Objective-C објекти. Типови вредности (struct, enum) не подржавају unowned јер не учествују у ARC-у.
Када је гаранција животног века апсолутна и очигледна — unowned је безбеднији са становишта дизајна: не захтева unwrap, не може бити nil, не маскира грешке. Ако објекат не може постојати без родитеља, unowned то чини изричитим уговором, а weak замагљује гаранцију.
Да: unowned је бржи јер не захтева приступ weak-табели runtime-а за нулирање. У већини апликација разлика је неприметна, али у високооптерећеним сценаријима са милионима приступа unowned може бити 10–20% бржи при читању.
Рефакторисање — главна опасност за unowned. Промена животног века објекта (кеширање, асинхроне операције, поновно коришћење) може нарушити гаранцију. Компајлер неће упозорити. Решење: мигрирајте на weak при промени архитектуре или додајте коментар упозорења.
Резиме
unowned let или unowned var; може бити non-optional и optional (Swift 5.0+)Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође