Ich surfe durch den wunderbaren Blog von Scott Stevenson und versuche, ein grundlegendes Objective-C-Konzept zu verstehen, bei dem Delegierten die Eigenschaft "Zuweisen" gegenüber "Beibehalten" zugewiesen wird. Beachten Sie, dass beide in einer Müllsammelumgebung gleich sind. Ich beschäftige mich hauptsächlich mit einer nicht GC-basierten Umgebung (z. B. iPhone).
Direkt aus Scotts Blog:
"Das Schlüsselwort assign generiert einen Setter, der den Wert direkt der Instanzvariablen zuweist, anstatt ihn zu kopieren oder beizubehalten. Dies ist am besten für primitive Typen wie NSInteger und CGFloat oder für Objekte geeignet, die Sie nicht direkt besitzen, z. B. Delegaten."
Was bedeutet es, dass Sie das Delegatenobjekt nicht direkt besitzen? Normalerweise behalte ich meine Delegierten, denn wenn ich nicht möchte, dass sie in den Abgrund gehen, kümmert sich Retain für mich darum. Normalerweise abstrahiere ich UITableViewController von seiner jeweiligen Datenquelle und delegiere auch. Ich behalte auch dieses spezielle Objekt. Ich möchte sicherstellen, dass es nie verschwindet, damit mein UITableView immer einen Delegierten hat.
Kann jemand weiter erklären, wo / warum ich falsch liege, damit ich dieses gängige Paradigma in der Objective-C 2.0-Programmierung verstehen kann, die Zuweisungseigenschaft für Delegaten zu verwenden, anstatt sie beizubehalten?
Vielen Dank!
quelle
Antworten:
Der Grund, warum Sie das Speichern von Delegierten vermeiden, besteht darin, dass Sie einen Aufbewahrungszyklus vermeiden müssen:
A erstellt B A setzt sich als B-Delegierter… A wird von seinem Eigentümer freigegeben
Wenn B A behalten hätte, würde A nicht freigegeben werden, da B A besitzt, so dass der Dealloc von A niemals aufgerufen würde, was dazu führen würde, dass sowohl A als auch B auslaufen.
Sie sollten sich keine Sorgen machen, dass A weggeht, weil es B besitzt und es somit im Dealloc loswird.
quelle
weak
? Die Frage ist, warumassign
statt verwendenweak
?assign
statt verwendenretain
. Die Frage ist älter als ARC;weak
undstrong
(letzteres ist synonym mitretain
) existierte nicht, bis ARC eingeführt wurde. Sie sollten Ihre Frage zuweak
vs.assign
separat stellen.Weil das Objekt, das die Delegatennachrichten sendet, den Delegaten nicht besitzt.
Oft ist es umgekehrt, als wenn sich ein Controller als Delegat einer Ansicht oder eines Fensters festlegt: Der Controller besitzt die Ansicht / das Fenster. Wenn also die Ansicht / das Fenster ihren Delegaten besitzt, besitzen sich beide Objekte gegenseitig. Dies ist natürlich ein Haltezyklus, ähnlich einem Leck mit der gleichen Konsequenz (Objekte, die tot sein sollten, bleiben am Leben).
In anderen Fällen handelt es sich bei den Objekten um Peers: Keiner besitzt den anderen, wahrscheinlich weil beide demselben dritten Objekt gehören.
In beiden Fällen sollte das Objekt mit dem Delegaten seinen Delegaten nicht behalten.
(Es gibt übrigens mindestens eine Ausnahme. Ich erinnere mich nicht, was es war, und ich glaube nicht, dass es einen guten Grund dafür gab.)
Nachtrag (hinzugefügt am 19.05.2012): Unter ARC sollten Sie
weak
anstelle von verwendenassign
. Schwache Referenzen werdennil
automatisch eingestellt, wenn das Objekt stirbt, wodurch die Möglichkeit ausgeschlossen wird, dass das delegierende Objekt am Ende Nachrichten an den toten Delegierten sendet.Wenn Sie sich aus irgendeinem Grund von ARC fernhalten, ändern Sie zumindest
assign
Eigenschaften, die auf Objekte verweisenunsafe_unretained
, wodurch deutlich wird, dass dies ein nicht beibehaltener, aber nicht auf Null setzender Verweis auf ein Objekt ist.assign
bleibt für Nicht-Objektwerte sowohl unter ARC als auch unter MRC geeignet.quelle
NSURLConnection
behält seinen Delegierten.weak
, aber das beantwortet nicht die ursprüngliche Frage: Warum verwendet Appleassign
anstelle vonweak
?assign
anstatt sie beizubehalten ? "weak
existierte nicht, als es gefragt wurde. Ihre Frage ist eine andere, die Sie separat stellen sollten. Ich würde gerne antworten.Beachten Sie, dass es bei einem zugewiesenen Delegaten sehr wichtig ist, diesen Delegatenwert immer auf Null zu setzen, wenn die Zuordnung des Objekts aufgehoben wird. Daher sollte ein Objekt immer darauf achten, keine Delegatenreferenzen in Dealloc auszuschließen, wenn dies nicht der Fall ist anderswo gemacht.
quelle
Einer der Gründe dafür ist die Vermeidung von Haltezyklen. Nur um das Szenario zu vermeiden, in dem A und B beide Objekte aufeinander verweisen und keines von ihnen aus dem Speicher freigegeben wird.
Die akute Zuweisung eignet sich am besten für primitive Typen wie NSInteger und CGFloat oder für Objekte, die Sie nicht direkt besitzen, z. B. Delegaten.
quelle