Speicherverwaltung – iOS | Komentor

Speicherdirektiven (Objective-C)

Möglicherweise haben Sie viele Zeilen eingegeben, die in etwa so aussehen.

@property (nichtatomar, stark) NSMutableArray *items`;

Dies ist eine ziemlich standardmäßige Eigenschaftsdeklaration, die Sie in einer .h-Datei oder am Anfang einer .m-Implementierungsdatei finden würden. Jetzt gibt nonatomic an, wie verschiedene Prozesse in einer Multithread-App mit einer Eigenschaft interagieren können. Wenn Sie sicherstellen möchten, dass Ihre Eigenschaft Thread-sicher ist, verwenden Sie das Attribut atomar anstelle von nicht atomar. Hier finden Sie weitere Details zum Multithreading. Strong hingegen ist eine Speicherdirektive.

stark (Erinnerungsdirektive) — bestimmt, wann wir die Referenzanzahl eines Objekts erhöhen und wann Speicher freigegeben werden kann.

Stark ist nur eine der Optionen, die wir haben, aber es ist die häufigste, die wir verwenden. Es ist auch dasselbe wie “retain”, das wir in Eigenschaftsdeklarationen vor ARC sehen würden.

Einfach ausgedrückt bedeutet stark, dass die Referenzanzahl erhöht wird und die Referenz darauf während der gesamten Lebensdauer des Objekts erhalten bleibt. Wenn der Zählwert Null erreicht, kann der Speicher freigegeben werden.

Schwach bedeutet, dass wir auf ein Objekt zeigen, aber seine Referenzanzahl nicht erhöhen. Es wird häufig verwendet, wenn eine Eltern-Kind-Beziehung erstellt wird. Der Elternteil hat einen starken Bezug zum Kind, aber das Kind hat nur einen schwachen Bezug zum Elternteil.

schreibgeschützt bedeutet, dass Sie die Eigenschaft zunächst festlegen können, dann aber nicht mehr ändern können. Dies könnte sich für alle möglichen Dinge als nützlich erweisen, die Sie nicht versehentlich ändern möchten.

Kopierenerstellt eine Kopie des zu referenzierenden Objekts. Es zeigt dann stattdessen auf die Kopie und setzt seinen Referenzzähler auf 1. Die Verwendung von Kopie bedeutet, dass wir den Wert des Objekts kopieren, wenn es erstellt wird. Dadurch wird verhindert, dass sich sein Wert ändert, wenn sich der Wert eines Objekts ändert, auf das es zeigt.

Retain-Zyklus (Objective-C)

Dies geschieht, wenn Objekte einen starken Bezug zueinander haben. Einfach ausgedrückt, ein Haltezyklus ist, wo x an y festhält und y an x ​​festhält, aber keine anderen Objekte sich mehr um x oder y kümmern. Aber Sie können sie immer noch nicht freigeben, weil sie sich aneinander festhalten, sodass sie beide auslaufen. Ein Retain-Zyklus, der etwas Kleines wie einige Zeichenfolgen oder Zahlen umfasst, verursacht möglicherweise keine merklichen Leistungsprobleme, aber wenn Sie den gleichen Code verwenden, um schwerere Elemente wie Audioclips oder große Objekte zu verarbeiten, kann es zu einem Absturz kommen. Dies kann oft bei einem Block passieren, bei dem der Block das Ding behält, das den Block erstellt hat, und nie freigegeben wird, sodass das Ding, das den Block erstellt hat, auch nie freigegeben wird. Dies ist ein Problem, das schwer zu lösen ist.

Schneller ARC

Wie Objective C verwendet Swift die automatische Referenzzählung (ARC). Viele der Überlegungen, die Sie anstellen müssen, sind ähnlich wie bei Objective-C, obwohl Sie sich insgesamt noch weniger Sorgen machen müssen.

Das erste, was Sie bei der Swift-Speicherverwaltung als anders bemerken werden, ist, dass wir Speicherdirektiven wie „strong“ und „copy“ nicht explizit deklarieren, wie dies bei Objective-C-Property-Deklarationen der Fall wäre. In Swift wird davon ausgegangen, dass alle Eigenschaften einer Klasse stark sind, sodass Sie einfach eine Eigenschaft deklarieren können, ohne „stark“ zu schreiben. Natürlich ist ‘Swift’, wie Objective-C, nicht immun gegen Retain-Zyklen. So oft müssen Sie explizit eine schwache Referenz angeben, beispielsweise zwischen einem Elternteil und einem Kind. Dazu müssen Sie das Schlüsselwort schwach verwenden.

Retain-Zyklus (Swift)

Wie ich oben erwähnt habe, können Sie bei starken Referenzen in beide Richtungen nicht beide Objekte freigeben, und es kommt zu einem Speicherleck.

Denken wir an die Situation, in der eines der Objekte niemals null sein könnte. Nehmen wir zum Beispiel an, wir haben einen Benutzer und einen Benutzer-Avatar. In diesem Szenario möchte ein Benutzer möglicherweise keinen Avatar haben und stattdessen nur ein Platzhalterbild anzeigen. Auf der anderen Seite muss jedoch ein Benutzer-Avatar mit einem Benutzer verknüpft sein. Ohne die Verknüpfung mit einem Benutzer hätte es in unserer App keine Bedeutung. In diesem Fall würden wir anstelle einer schwachen Referenz eine unbesessene Referenz wie diese verwenden.

class User: NSObject {
    var avatar: Avatar?
}
class Avatar: NSObject {
    unowned var user: User
}

Das letzte Szenario ist eines, in dem kein Mitglied der Beziehung jemals Null sein sollte.

Zum Beispiel zwischen zwei Objekten, Auto und Nummernschild. Keiner sollte ohne Verbindung zum anderen existieren.

class Car {
    var licencePlateNumber: LicencePlateNumber!
    init(licencePlateNumber: LicencePlateNumber) {
        self.licencePlateNumber = LicencePlateNumber(car: self)
    }
}
class LicencePlateNumber {
    unowned let car: Car
    init(model: String, licencePlateNumber: LicencePlateNumber) {
        self.car = car
    }
}

Hier sehen Sie, dass wir eine explizit ausgepackte Option in der Autoklasse kombiniert haben, zusammen mit einer nicht im Besitz befindlichen Referenz, die von der LicencePlateNumber auf das Auto zeigt.

So wie die Blöcke in Objective-C anfällig für Speicherprobleme sind, ist es nicht verwunderlich, dass ihr Swift-Gegenstück, Closures, es auch sind. Nun könnte eine Schließung auf verschiedene Weise einen starken Referenzzyklus verursachen. Im Allgemeinen tritt dies jedoch auf, wenn Sie einer Eigenschaft einer Klasseninstanz einen Abschluss zuweisen und dieser Abschluss selbst die Instanz erfasst. Weitere Informationen zu Schließungen und Erfassungslisten.

Similar Posts

Leave a Reply

Your email address will not be published.