Strong Reference (starke Referenz): Was es ist, Funktionsweise und ARC

Autor: IT Sectr Veröffentlicht: 2026-03-30 Lesezeit: 9 Min.

Strong Reference (starke Referenz) ist ein standardmäßiger Speicherverwaltungsmechanismus, bei dem ein Objekt im Speicher bleibt, solange mindestens eine aktive Referenz darauf zeigt. Im Gegensatz zu schwachen Referenzen erhöht eine starke Referenz den Referenzzähler des Objekts und verhindert seine automatische Freigabe. Laut der Apple Developer Documentation verwaltet ARC automatisch die Lebensdauer von Objekten in Swift und Objective-C. Das Verständnis der Funktionsweise starker Referenzen ist entscheidend für die Vermeidung von Speicherlecks und zyklischen Abhängigkeiten in mobilen Anwendungen.

Wichtige Punkte

  • Strong Reference — ein Verweis, der ein Objekt im Speicher hält, indem er seinen retain count um 1 erhöht.
  • ARC fügt automatisch retain- und release-Operationen ein und macht die manuelle Speicherverwaltung in Swift und Objective-C überflüssig.
  • Retain cycle entsteht, wenn zwei Objekte einander über starke Referenzen referenzieren — der Speicher wird nie freigegeben.
  • Weak Reference erhöht den Referenzzähler nicht und wird bei Freigabe des Objekts automatisch nil.
  • Unowned Reference erhöht den Zähler nicht, geht jedoch davon aus, dass das Objekt nicht länger lebt als sein Besitzer.

Was ist Strong Reference?

Strong Reference ist eine Art von Verweis auf ein Objekt, der seine Zerstörung durch den Garbage Collector oder das Speicherverwaltungssystem verhindert. Solange mindestens eine starke Referenz auf das Objekt existiert, wird sein Speicher nicht freigegeben. Dies ist der grundlegende Mechanismus, auf dem ARC in Swift und Objective-C sowie die Garbage Collection in Java und Kotlin basieren.

Das Konzept der starken Referenz ist grundlegend für alle Sprachen mit automatischer Speicherverwaltung. In Systemen mit ARC erhöht jede starke Referenz den Referenzzähler des Objekts. Wenn der Zähler auf Null fällt, wird das Objekt sofort freigegeben. In Java und Kotlin mit Garbage Collection stellt eine starke Referenz sicher, dass das Objekt erreichbar ist und nicht vom GC eingesammelt wird.

Laut WWDC 2021 stehen etwa 35% der Speicherlecks in iOS-Anwendungen im Zusammenhang mit der falschen Verwendung von starken Referenzen und Retain Cycles. In der Android-Entwicklung sind Lecks durch implizite starke Referenzen in Closures und Callbacks die zweithäufigste Ursache für Speicherprobleme nach Context Leak.

Um effektiv mit Speicher zu arbeiten, müssen Sie den Unterschied zwischen strong-, weak- und unowned-Referenzen verstehen und den richtigen Referenztyp basierend auf dem Besitz und der Lebensdauer der Objekte wählen.

Wie ARC die Speicherverwaltung verändert hat

Vor ARC mussten Entwickler für jedes Objekt manuell retain und release aufrufen, was zu zahlreichen Fehlern führte. ARC, das von Apple im Jahr 2011 mit LLVM 3.0 eingeführt wurde, automatisierte diesen Prozess durch die Analyse des Besitzgraphen zur Kompilierzeit. Der Compiler selbst fügt retain-, release- und autorelease-Aufrufe an den erforderlichen Stellen ein.

Laut Clang Static Analyzer reduzierte die Einführung von ARC speicherbezogene Fehler in iOS-Anwendungen um 70%. Für Entwickler bedeutet dies, dass die Speicherverwaltung sicherer geworden ist, aber gleichzeitig die Notwendigkeit entstanden ist, zu verstehen, wie starke Referenzen unter der Haube funktionieren — um Retain Cycles zu vermeiden.

In Kotlin und Java spielt der Garbage Collector die Rolle von ARC, aber das Prinzip der starken Referenz bleibt dasselbe: GC Roots sind die Einstiegspunkte, durch die Objekte von starken Referenzen gehalten werden. Solange ein Objekt über eine Kette starker Referenzen von einer GC Root aus erreichbar ist, wird es nicht eingesammelt.

Wie funktioniert Strong Reference in ARC?

ARC (Automatic Reference Counting) funktioniert durch Zählen der Referenzen für jedes Objekt im Heap. Wenn eine neue starke Referenz auf ein Objekt erstellt wird, erhöht sich der Zähler (retain). Wenn die Referenz zerstört oder überschrieben wird, verringert sich der Zähler (release). Wenn der Zähler Null erreicht, wird das Objekt sofort aus dem Speicher entfernt.

Betrachten wir ein Beispiel in Swift. Beim Erstellen einer Klasseninstanz reserviert ARC Speicher und setzt den retain count auf 1. Jede neue Zuweisung an eine andere Variable erhöht den Zähler. Wenn die Variable den Gültigkeitsbereich verlässt, verringert sich der Zähler:

swift
class ProfileViewController {
    var nameLabel: String?
    var avatarImage: UIImage?

    func loadProfile() {
        // retain count = 1 für neue Instanz
        let user = User(name: "Ivan")
        // retain count = 2 nach Zuweisung von nameLabel
        nameLabel = user.name
        // Methodenausgang — user verlässt den Gültigkeitsbereich, retain count = 1
    }
}

In diesem Code stellt ARC sicher, dass das User-Objekt im Speicher bleibt, solange mindestens eine starke Referenz darauf zeigt. Wenn die Funktion loadProfile beendet wird, wird die lokale Variable user zerstört, aber nameLabel hält das Objekt weiterhin. Der Speicher wird erst freigegeben, wenn nameLabel nicht mehr existiert oder überschrieben wird.

In Kotlin wird ein ähnliches Verhalten durch GC Roots bereitgestellt. Solange eine verfolgbare Kette starker Referenzen von einer Garbage-Collector-Wurzel (z. B. einem statischen Feld oder einem aktiven Thread) existiert, bleibt das Objekt im Speicher. Der Unterschied besteht darin, dass der GC den Speicher nicht sofort freigibt — dies geschieht asynchron nach der Erreichbarkeitsanalyse.

Wann erfolgt die Speicherfreigabe

In ARC erfolgt die Freigabe synchron, wenn der Zähler Null erreicht. In Swift und Objective-C wissen Sie genau, wann das Objekt entfernt wird. In Kotlin und Java ist der Zeitpunkt der Freigabe unvorhersehbar, aber dies wird durch ein flexibleres Schema zur Erkennung zyklischer Abhängigkeiten auf der Ebene des Garbage Collectors ausgeglichen.

Retain Cycles und Speicherlecks

Retain cycle (Haltezyklus) — eine Situation, in der zwei oder mehr Objekte gegenseitige starke Referenzen aufeinander haben. Infolgedessen fällt ihr retain count nie auf Null und der Speicher wird nie freigegeben, selbst nachdem die Objekte für die Anwendung nicht mehr benötigt werden.

Ein klassisches Beispiel: Ein Eltern-View-Controller hält ein Kind-Objekt mit einer starken Referenz, und dieses hält wiederum den Eltern mit einer starken Referenz. Dies ist typisch für Situationen mit Delegaten, Closures und verschachtelten Lambda-Ausdrücken. Laut Instruments Leaks machen Retain Cycles bis zu 60% aller Speicherlecks in Anwendungen aus, die ARC verwenden.

swift
class ParentViewController: UIViewController {
    var child: ChildViewController?

    func setupChild() {
        child = ChildViewController()
        // retain cycle: Eltern hält Kind, Kind hält Eltern über Closure
        child?.onEvent = {
            self.handleEvent()
        }
    }

    func handleEvent() {}
}

Das Problem hier ist, dass die Closure onEvent self (ParentViewController) mit einer starken Referenz erfasst und ParentViewController selbst child mit einer starken Referenz hält. Beide Objekte werden nie freigegeben. Die Lösung ist die Verwendung von weak self in der Closure, um den Zyklus zu durchbrechen.

In Kotlin entstehen ähnliche Zyklen bei der Verwendung von Lambdas, die externe Objekte erfassen. Der JVM-Garbage-Collector kann solche Zyklen mit der Zeit erkennen, aber nur, wenn die Objekte von GC Roots aus nicht erreichbar sind. Wenn der Zyklus an einen aktiven Thread oder UI-Kontext gebunden ist, bleibt das Leck für die gesamte Lebensdauer der Anwendung bestehen.

Strong vs Weak vs Unowned Reference

Den Unterschied zwischen Referenztypen zu verstehen, ist der Schlüssel zur sicheren Speicherverwaltung. Strong Reference erhöht den retain count. Weak Reference erhöht den retain count nicht und wird bei Freigabe des Objekts automatisch nil. Unowned Reference erhöht den retain count ebenfalls nicht, wird aber nicht auf null gesetzt — der Zugriff darauf nach der Freigabe verursacht einen Absturz.

ReferenztypRetain countSicherheitVerwendung
Strong+1Sicher (Standard)Objektbesitz, Eltern → Kind-Beziehung
WeakÄndert nichtAuto-Nullsetzung (sicher)Delegaten, Callbacks, Rückverweise
UnownedÄndert nichtAbsturzrisiko bei spätem ZugriffWenn das Objekt garantiert länger lebt als der Besitzer

Die Wahl des Referenztyps wird durch die Besitzbeziehung bestimmt. Wenn Objekt B Teil von A ist und ohne es nicht existieren kann — verwenden Sie Strong. Wenn B unabhängig existieren kann und A für Benachrichtigungen referenziert — verwenden Sie Weak. Unowned wird selten verwendet — nur wenn die Lebensdauer des Kind-Objekts die des Elternteils nicht überschreitet.

Praktische Auswahlregel

Apple Developer Documentation empfiehlt: Standardmäßig strong für alle Besitzbeziehungen verwenden. Wenn Sie einen Retain Cycle vermeiden müssen — bestimmen Sie, welche Referenz schwach sein sollte. In der Regel ist dies der Rückverweis in der Hierarchie (Kind → Eltern). In Kotlin spielt WeakReference aus java.lang.ref eine ähnliche Rolle, das für Caches und Observer-Muster verwendet wird.

Wie man Probleme mit starken Referenzen behebt

Retain Cycles zu erkennen ist der erste Schritt. Der zweite ist ihre korrekte Beseitigung. Das wichtigste Werkzeug zum Durchbrechen von starken Referenzzyklen ist das Ersetzen einer der Referenzen durch weak oder unowned. In Sprachen mit Garbage Collection wird zusätzlich WeakReference mit manueller Null-Prüfung vor jedem Zugriff verwendet.

In Swift und Objective-C ist die häufigste Korrektur das Hinzufügen von [weak self] in Closures. Dies stellt sicher, dass die Closure das Objekt nach seiner Freigabe nicht zurückhält. In Kotlin werden WeakReference-Wrapper oder explizite Referenzbereinigung in onDestroy für ähnliche Zwecke verwendet.

swift
class NetworkService {
    func fetchData(completion: @escaping (Data?) -> Void) {
        // Erfassung über weak self — retain cycle ausgeschlossen
        URLSession.shared.dataTask(
            with: URL(string: "https://api.example.com")!
        ) { [weak self] data, response, error in
            guard let self else { return }
            completion(data)
        }.resume()
    }
}

In diesem Beispiel stellt [weak self] sicher, dass NetworkService nach seiner Nichtmehrbenötigung nicht von der Closure zurückgehalten wird. Wenn self vor Abschluss der Anfrage freigegeben wird — guard let self else { return } verlässt die Closure ohne Aufruf von completion.

Für die Diagnose von Retain Cycles verwenden Sie Instruments Leaks für iOS oder Android Profiler + LeakCanary für Android. Diese Tools zeigen den genauen Haltegraph an und geben an, welche starke Referenz die Freigabe des Objekts verhindert. Regelmäßiges Speicher-Profiling sollte Teil der CI/CD-Pipeline jedes mobilen Projekts sein.

Strong Reference in Swift und Kotlin — Vergleich

Swift und Kotlin verwenden grundlegend unterschiedliche Speicherverwaltungsmechanismen, aber das Konzept der starken Referenz existiert in beiden. Swift verwendet ARC mit synchroner Freigabe bei retain count = 0. Kotlin verwendet einen verfolgenden GC, der asynchron nicht erreichbare Objekte bereinigt.

ParameterSwift (ARC)Kotlin (JVM GC)
MechanismusReferenzzählung (retain count)Erreichbarkeitsverfolgung (GC Roots)
FreigabeSynchron (bei Zähler Null)Asynchron (durch GC-Zyklus)
Retain cycleWird nicht automatisch erkanntGC kann erkennen, aber nicht sofort
Weak refweak (Auto-Nullsetzung)WeakReference (manuelle Prüfung)

Der wichtigste praktische Unterschied: In Swift ist ein Retain Cycle ein garantiertes Leck. In Kotlin kann der GC den Zyklus brechen, wenn die Objekte von der Wurzel aus nicht erreichbar sind, aber die Lebensdauer der ausgelaufenen Objekte bleibt unvorhersehbar. Daher ist in beiden Sprachen die beste Strategie, starke Referenzzyklen bereits in der Entwurfsphase zu vermeiden.

Für Swift verwenden Sie weak in Delegatenmustern und Closures. Für Kotlin verwenden Sie WeakReference oder Lifecycle-aware-Komponenten, die Referenzen bei Zerstörung des Besitzers automatisch löschen. In beiden Ansätzen ist das Ziel dasselbe — starke Referenzen dort zu eliminieren, wo sie eine unzerbrechliche Haltekette erzeugen.

Häufig gestellte Fragen

Wie unterscheidet sich Strong Reference von Weak Reference?

Strong Reference erhöht den retain count des Objekts und verhindert seine Freigabe, solange die Referenz existiert. Weak Reference ändert den retain count nicht und wird automatisch nil, wenn das Objekt aus dem Speicher entfernt wird. Starke Referenzen werden für den Besitz verwendet, schwache für Rückverbindungen und Delegaten.

Was ist ein Retain Cycle und warum ist er gefährlich?

Retain cycle — eine gegenseitige Blockade, bei der zwei Objekte einander mit starken Referenzen halten. Ihr retain count fällt nie auf Null, der Speicher wird nicht freigegeben. Dies führt zu Speicherlecks: Die Objekte bleiben für immer im Heap, die Anwendung verbraucht immer mehr Ressourcen und stürzt schließlich mit OutOfMemory ab.

Wie erkennt man einen Retain Cycle in einer iOS-Anwendung?

Verwenden Sie Instruments Leaks aus Xcode — führen Sie die Profilerstellung mit der Leaks-Vorlage aus, führen Sie ein Szenario in der App aus und überprüfen Sie die Leck-Indikatoren. Für eine genaue Diagnose wechseln Sie zum Tab Cycles & Roots — er zeigt den Graphen der gegenseitigen starken Referenzen an, die einen unzerbrechlichen Zyklus bilden.

Wann sollte Unowned anstelle von Weak verwendet werden?

Unowned sollte verwendet werden, wenn die Lebensdauer des Kind-Objekts garantiert die des Elternteils nicht überschreitet — zum Beispiel beim Binden eines Objekts an einen streng definierten Gültigkeitsbereich. Im Zweifelsfall verwenden Sie Weak, da der Zugriff auf eine freigegebene unowned-Referenz einen Anwendungsabsturz verursacht.

Beeinflussen starke Referenzen die Anwendungsleistung?

Indirekt — ja. Jeder retain und release in ARC ist eine atomare Operation mit Overhead. Bei einer großen Anzahl von Objekten in Zyklen kann dies die Leistung beeinträchtigen. Das Hauptproblem ist jedoch nicht die Geschwindigkeit von ARC, sondern Speicherlecks aufgrund eines falsch gewählten Referenztyps.

Zusammenfassung

  • Strong Reference ist der grundlegende Mechanismus des Objektbesitzes, der das Objekt durch Erhöhung des retain count im Speicher hält.
  • ARC automatisiert die Speicherverwaltung in Swift und Objective-C, eliminiert manuelles retain und release, schützt jedoch nicht vor Retain Cycles.
  • Retain cycle entsteht bei gegenseitigen starken Referenzen — dies ist die Hauptursache für Speicherlecks in ARC-Systemen.
  • Weak und Unowned Referenzen durchbrechen starke Referenzzyklen, ohne den retain count zu erhöhen.
  • Die Wahl des Referenztyps wird durch die Besitzbeziehung bestimmt: Strong für Eltern→Kind, Weak oder Unowned für Kind→Eltern.
  • Instruments Leaks und LeakCanary sind die wichtigsten Werkzeuge zur Erkennung problematischer starker Referenzen in iOS und Android.
  • Entwerfen Sie den Besitzgraphen im Voraus — das ist günstiger als die Behebung von Speicherlecks nach der Veröffentlichung der Anwendung.

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch