2017-10-27 1 views
2

Nehmen wir an, wirVerwirrungen über die schwache Delegat in schnellen

protocol MyProtocol { 
    fun someFunc() 
} 

class AClass { 
    var delegate: MyProtocol? 
} 

AClass kümmert sich nicht darum, ein Protokoll, wenn der Delegierte eine Klasse oder Struktur ist. Was ich will, ist manchmal der Delegat kann eine Klasse sein und manchmal kann es einer Struktur zugewiesen werden.

Meine Frage ist, ob ich den Delegierten "schwach" machen sollte.

Wenn ja, muss ich MyProtocol ein "Klassenprotokoll" sein, so dass der Delegat nur eine Klasse sein muss. Wenn nicht, wenn ich den Delegaten Klasse zuweisen, wie kann ich Retain-Zyklus vermeiden?

Danke für jeden Hinweis!

Antwort

2

sollte der Delegierte treffen zu „schwach“

Die Antwort ist, dass, wenn MyProtocol nicht auf Klassen beschränkt ist, können Sie es nicht schwach machen, wird der Compiler nicht im Stich lassen.

Der Grund dafür ist, dass struct s Werttypen sind. Es gibt keine Referenz, die stark oder schwach sein kann, da die gesamte Struktur bei der Zuweisung des Delegaten logisch kopiert wird.

Wie kann ich Retain-Zyklus vermeiden?

Dies bedeutet, dass Sie darauf achten müssen, dass Ihr Delegat keine starken Referenzen zurück zu der Instanz der Klasse enthält. So zum Beispiel

struct ConcreteDelegate: MyProtocol 
{ 
    fun someFunc() {} 
    var instance: AClass 

    init() 
    { 
     instance = AClass() 
     instance.delegate = self 
    } 
} 

Verursacht einen Referenzzyklus. Es kann, indem er erklärt instance als

weak var instance: AClass! 

Alternativ und eine bessere Lösung (IMO), Ihre Protokollfunktionen der Instanz gebrochen werden als Parameter übergeben kann, so dass die Delegierten nie einen Verweis auf die Instanz speichern muss.

Sie werden den oben genannten Ansatz in Cocoa in vielen Orten, zum Beispiel mit dem Tabellenansicht Datenquellenprotokoll angenommen.

+0

Danke für Ihre Antwort! – echo

0

Ich denke, dass Sie vergessen haben, dass struct nicht Referenztyp aber ein Werttyp sind. Das bedeutet, dass eine Klasse im Speicher-Heap einen Verweis hat, aber Strukturen, Enums nicht. Wenn Sie sich diese Tatsache merken, gibt es keine Bedeutung weak zu setzen, wenn der Delegat Ihres Protokolls ein struct ist, weil es einen Retain-Zyklus nicht verursachen kann.

Sie müssen sich Gedanken über Retain-Zyklen machen, wenn Sie nur Klassen verwenden. Wenn Ihr Delegierter Ihres Protokolls eine Klasse ist, setzen Sie weak, wenn Sie der Meinung sind, dass Ihre Klasse eine Referenz Ihres Protokolls hat UND Ihr Protokoll eine Referenz Ihrer Klasse haben kann, setzen Sie weak, das ist der Retain-Zyklus.

Wenn Sie es überprüfen möchten, setzen Sie deinit Funktionen, wenn Sie testen und sehen, ob Ihre Klasse korrekt deinit und nicht im Speicher gehalten wird. Es ist im Grunde, was ich weiß, hoffe, es wird dir helfen.