Unowned Reference: co to je, syntaxe a použití v mobilních aplikacích

Autor: IT Sectr Publikováno: 2026-03-30 Doba čtení: 9 min

Unowned Reference (reference bez vlastníka) — je nevlastnící reference ve Swift, která nezvyšuje retain count objektu a na rozdíl od weak se po uvolnění objektu nenastavuje na nil. Podle Apple Swift Language Guide, 2026 se unowned používá, když je zaručeno, že objekt žije alespoň tak dlouho jako objekt, který se na něj odkazuje. Na rozdíl od Weak Reference unowned nevyžaduje unwrap — je to non-optional typ, který dělá kód čistším, ale klade odpovědnost za záruku životnosti na vývojáře.

Hlavní body

  • Unowned Reference — nevlastnící reference bez automatického nulování; non-optional, nezvyšuje retain count
  • Záruka — používá se, když objekt nemůže být garantovaně uvolněn dříve než odkazující se objekt
  • Rozdíl od weak — unowned se nenuluje na nil (riziko crash), weak se nuluje (bezpečné)
  • Scénáře — parent-child se zárukou života, uzávěry s unowned self, singly a Service Locator
  • Riziko — přístup k uvolněnému unowned objektu způsobí runtime crash (EXC_BAD_ACCESS)

Co je Unowned Reference?

Unowned Reference — je nevlastnící reference na objekt v ARC, která nezvyšuje jeho retain count. Na rozdíl od weak se unowned po dealokaci objektu nenuluje: nadále ukazuje na oblast paměti, která již byla uvolněna. Přístup k takové referenci způsobí runtime crash s EXC_BAD_ACCESS.

Termín „bez vlastníka” odráží sémantiku: objekt existuje, ale nikdo nenese odpovědnost za jeho životnost. Vývojář výslovně prohlašuje: „garantuji, že tento objekt bude žít, dokud se na něj odkazuji”. Kompilátor tuto záruku nekontroluje — je to kontrakt na úrovni vývojáře.

Podle Swift.org Documentation, 2026 jsou unowned reference preferovány před weak ve scénářích s garantovanou životností, protože: nevyžadují volitelný typ (čistší kód), nevyžadují unwrap (méně force-unwrap nebo guard let) a nemají režii na udržování zeroing weak tabulky. Nicméně jakékoli porušení kontraktu — crash.

Syntaxe unowned ve Swift

Ve Swift se unowned reference deklarují klíčovým slovem unowned před let nebo var. Na rozdíl od weak může být unowned jak let, tak var a nevyžaduje volitelný typ. Tato vlastnost činí unowned vhodným pro reference, které podle doménové logiky nemohou být nil.

swift
class Country {
    let name: String
    var capital: City!           // bude nastaveno po inicializaci
    init(name: String) { self.name = name }
}

class City {
    let name: String
    unowned let country: Country   // unowned let — záruka života

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

// Použití
let france = Country(name: "France")
let paris = City(name: "Paris", country: france)
france.capital = paris
// Country → City (strong), City → Country (unowned) — bez retain cycle

V tomto příkladu City unowned let country — město nemůže existovat bez země. Pokud země zmizí, město (a reference) ztratí smysl. Sémanticky je to ideální případ pro unowned: záruka životnosti existuje, optional není potřeba, retain cycle nevzniká.

unowned var

unowned var je povoleno, ale vyskytuje se méně často. Používá se, když může být reference nahrazena (např. přepojení dítěte k jinému rodiči). Při nahrazení je uvolnění starého objektu odpovědností externího vlastníka.

Unowned Optional

V Swift 5.0+ byla přidána podpora pro unowned optional (unowned let x: Type?). To je kompromis: unowned zaručuje, že pokud reference není nil, objekt žije. Chování při uvolnění — crash, jako u běžného unowned.

Unowned vs Weak: kdy co použít

Volba mezi unowned a weak — jedno z častých rozhodnutí při navrhování Swift architektury. Podívejme se na kritéria a doporučení pro každý případ.

KritériumWeakUnowned
OptionalAno (Type?)Ne (Type)
Nulování při dealokaciAuto na nilNe (riziko visícího ukazatele)
Typ (let/var)Pouze varlet nebo var
VýkonRežie pro weak tabulkuMinimální (jednoduchý ukazatel)
BezpečnostBezpečné (nil se kontroluje)Riziko EXC_BAD_ACCESS
Záruka životnostiNení vyžadovánaVyžaduje výslovnou záruku

Praktické pravidlo

Použijte weak, pokud existuje byť jen sebemenší pochybnost o životnosti objektu. Weak je bezpečný, srozumitelný a nevyžaduje důkazy. Použijte unowned pouze když jste vyloučili všechny scénáře, při kterých by objekt mohl být uvolněn dříve. Typické případy: dítě, které neexistuje bez rodiče; uzávěrka, která se provádí synchronně; odkaz na objekt v rámci jeho inicializátoru.

Podle Airbnb Swift Style Guide, 2025 se ve velkých kódových základnách doporučuje používat weak standardně a unowned — pouze s výslovným komentářem vysvětlujícím záruku životnosti. To snižuje riziko neočekávaných crashů při refaktorování.

Unowned self v uzávěrách

Uzávěrky (closures) — druhý nejčastější scénář použití unowned po parent-child vztazích. Capture list [unowned self] se používá, když je zaručeno, že self žije déle než uzávěrka. Podívejme se na správné a nesprávné scénáře.

Kdy je unowned self bezpečné

Synchronní uzávěrky — sorted, filter, map. Provádějí se okamžitě v aktuálním vlákně, self určitě žije. Capture list s unowned je zde přijatelný a dává čistší kód.

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

    func processSorted() {
        // unowned self — sorted se provádí synchronně, self zaručeně žije
        let sorted = items.sorted { [unowned self] a, b in
            return self.customCompare(a, b)
        }
    }

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

Kdy je unowned self nebezpečné

Asynchronní uzávěrky — se zpožděním, síťovými požadavky, animacemi. Self může být uvolněno mezi umístěním uzávěrky a jejím provedením. Zde unowned self → crash. Použijte [weak self].

swift
class NetworkLoader {
    func loadData() {
        // NEBEZPEČNÉ: unowned self v asynchronním uzávěru
        URLSession.shared.dataTask(with: url) { [unowned self] data, _, _ in
            self.handleResponse(data)  // CRASH pokud je self uvolněno
        }.resume()
    }

    func handleResponse(_ data: Data?) { }

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

Zapamatujte si pravidlo: unowned self — pouze pro synchronní uzávěrky provádějící se okamžitě. Pro asynchronní — vždy weak self + guard let. Výjimka: pokud výslovně držíte referenci na objekt do dokončení uzávěrky (např. uložením silného capture do jiné proměnné).

Rizika unowned a jak se jim vyhnout

Unowned — mocný, ale nebezpečný nástroj. Podívejme se na reálné scénáře, kde unowned může vést k crash, a metody minimalizace rizika.

Refaktorování a změna záruk

Hlavní riziko unowned — změna obchodní logiky, při které záruka životnosti přestává platit. Vývojář refaktoruje kód: mění vlastnictví, zavádí odložené uvolňování, přidává cachování — a unowned reference se mění v časovanou bombu. Kompilátor nevaruje — pouze crash na zařízení uživatele.

Doporučení: používejte unowned pouze když je záruka životnosti zřejmá a zdokumentovaná. Přidejte komentář ke každému unowned: proč je tato reference bezpečná a za jakých podmínek může být porušena.

Unowned v hierarchiích UIKit

UIKit — zóna zvýšeného rizika pro unowned. ViewController může být uvolněn kdykoli při navigaci (pop, dismiss), uvolnění z paměti, změně orientace. Pokud předáte ViewController do uzávěrky s unowned self — při návratu z pozadí nebo dokončení animace může být self nil.

Nejlepší praktiky

Pro snížení rizika při používání unowned dodržujte tato pravidla:

  • Preferujte weak standardně — weak je bezpečný, unowned je optimalizace, ne standard
  • Dokumentujte záruky — ke každému unowned pište komentář s odůvodněním
  • Vyhněte se unowned ve ViewController — životní cyklus UIKit je pro unowned záruky nepředvídatelný
  • Používejte unowned pouze pro synchronní uzávěrky — sorted, filter, map — bezpeční kandidáti
  • Kontrolujte při code review — každé unowned vyžaduje odůvodnění od autora kódu
  • Migrujte na weak při sebemenší pochybnosti — ztráta v čitelnosti (jeden guard let) je menší než crash v produkci
swift
// Příklad: dokumentovaná unowned reference s explicitním odůvodněním
class InvoiceLineItem {
    let productName: String
    let price: Decimal

    // unowned Invoice — InvoiceLineItem nemůže existovat bez Invoice.
    // Invoice vytváří Item a maže jej při svém smazání.
    // Záruka: Invoice žije nejméně tak dlouho jako Item.
    unowned let invoice: Invoice

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

// To je silná záruka: Invoice maže všechny Item v deinit.
// porušení záruky = chyba v obchodní logice, kterou je třeba opravit.

Dokumentování záruk — profesionální standard. Ve velkých projektech (Airbnb, Uber) code review vyžaduje odůvodnění každého unowned. Pokud záruka není zřejmá — použijte weak. Komentář k unowned pomáhá budoucím vývojářům pochopit, proč zde není weak a jaké podmínky mohou záruku porušit.

Často kladené otázky

Co se stane při přístupu k unowned referenci po uvolnění objektu?

Runtime crash s EXC_BAD_ACCESS. Swift nekontroluje platnost unowned reference při přístupu — je to jen „surový” ukazatel. Pokud byl objekt uvolněn, paměť je přepsána a přístup k ní končí crash. Toto je nezachytitelná výjimka (není try-catch).

Lze unowned použít s protokoly?

Ano, pokud protokol dědí z AnyObject. Unowned funguje se všemi referenčními typy: třídy, protokoly AnyObject, Objective-C objekty. Hodnotové typy (struct, enum) nepodporují unowned, protože se neúčastní ARC.

Kdy je unowned bezpečnější než weak?

Když je záruka životnosti absolutní a zřejmá — unowned je bezpečnější z hlediska návrhu: nevyžaduje unwrap, nemůže být nil, neskrývá chyby. Pokud objekt nemůže existovat bez rodiče, unowned z toho dělá výslovný kontrakt, zatímco weak záruku rozmazává.

Je rozdíl ve výkonu mezi unowned a weak?

Ano: unowned je rychlejší, protože nevyžaduje přístup k weak tabulce runtime pro nulování. Ve většině aplikací je rozdíl neznatelný, ale ve vysoce zatížených scénářích s miliony přístupů může být unowned o 10–20% rychlejší při čtení.

Jak refaktorování ovlivňuje unowned záruky?

Refaktorování — hlavní nebezpečí pro unowned. Změna životnosti objektu (cachování, asynchronní operace, opětovné použití) může porušit záruku. Kompilátor nevaruje. Řešení: migrujte na weak při změně architektury nebo přidejte varovný komentář.

Shrnutí

  • Unowned Reference — nevlastnící reference bez nulování; non-optional, nezvyšuje retain count
  • Záruka — vyžaduje výslovný důkaz, že objekt žije alespoň tak dlouho jako kód, který se na něj odkazuje
  • Syntaxeunowned let nebo unowned var; může být non-optional a optional (Swift 5.0+)
  • Unowned vs Weak — unowned je rychlejší a čistší, ale weak je bezpečnější; weak — výchozí volba
  • Uzávěrky — unowned self pouze pro synchronní uzávěrky; asynchronní vyžadují [weak self]
  • Dokumentace — každé unowned by mělo mít komentář s odůvodněním záruky
  • Doporučení — při pochybnostech zvolte weak; unowned — pro výslovné a zdokumentované kontrakty

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také