2016-05-10 7 views
6

Nachdem ich einige Beiträge hier zu diesem Thema gelesen habe, entdeckte ich, dass mein Protokoll von 'Klasse' erben sollte, um 'schwach' an meinem zu arbeiten Delegate Variable.Swift: wie umgehen Problem, wo schwache Variable vom Typ 'Protokoll' illegal ist

"schwach" kann nur auf Klassen- oder Klassengebundene Protokolltypen angewendet werden.

Wenn mein Protokoll nicht von "Klasse" erbt, folgert schnell, dass es schwach sein sollte?

Ist dies die De-facto-Methode, um eine Variable vom Typ 'Protokoll' zu schwach zu machen?

Was einfach gebunden mit : class

protocol FacebookLoginViewControllerDelegate: class { 
    func facebookLoginViewControllerDidLogin(controller: FacebookLoginViewController) 
} 

class FacebookLoginViewController: UIViewController { 

    weak var delegate: FacebookLoginViewControllerDelegate? 

} 
+0

Ist dies hilft Ihnen http://StackOverflow.com/a/24104371/1371853 – swiftBoy

+1

Ich bin mir nicht sicher, was Sie hier fragen ... Eine Protokollklasse gebunden (': class') sagt einfach dem Compiler, dass es kann immer nur einen Referenztyp darstellen - und deshalb können Sie "schwach" darauf verwenden. Sie können keinen Wert als "schwach" angeben, da ARC (automatische * Referenz * zählen) mit Referenzen und nicht mit Werten arbeitet. – Hamish

+0

scheint eine vernünftige Antwort zu sein. Lust, das als Antwort zu posten? –

Antwort

9

Erstellen einer Protokollklasse in Bezug auf die Speicherverwaltung geschieht weist den Compiler an, dass sie einen Referenztyp immer nur darstellen können - und Sie können daher das weak Attribut auf sie aus.

Wenn Sie ein Protokoll nicht als klassengebunden markieren, wird Swift annehmen, dass es entweder einen Referenz- oder Werttyp darstellen könnte. Da ARC (automatisch Referenz counting) nur mit Verweisen und nicht mit Werten funktioniert, verhindert der Compiler, dass Sie das Attribut weak darauf setzen können.

Der Grund, dass ARC nicht mit Werttypen funktioniert, ist, dass sie kopiert werden, wenn Sie sie weitergeben, anstatt durch Verweis herumgereicht werden. Daher kann ihr Speicher leicht verwaltet werden, da ihre Lebensdauer im Gegensatz zu Referenztypen super vorhersehbar ist.

Wenn Sie als Referenztyp ein Delegatenmuster verwenden, sollte delegate immer weak sein, um Wiederholungszyklen zu vermeiden - und daher sollte das Protokoll immer klassengebunden sein. Die Verwendung eines Werttyps für einen Delegaten ist nahezu sinnlos, da er sich immer auf eine Kopie dessen bezieht, was Sie ihm zugewiesen haben.

+0

Habe ich das richtig verstanden: Wenn ich in der Lage sein will, dass Strukturen und Klassen meinem Protokoll entsprechen, gibt es keine Möglichkeit, Retain-Zyklen zu vermeiden? – shallowThought

+0

@ShallowThought Ich meine, Sie könnten einen Wrapper-Typ dafür erstellen (https://gist.github.com/hamishknight/71b851e495c46f036110e509d2cad63b), aber das deutet wahrscheinlich darauf hin, dass etwas mit Ihrem Protokolldesign nicht stimmt; Wenn Sie eine schwache Referenzsemantik wünschen, sollten die konformen Typen eigentlich alle Referenztypen sein (das Protokoll sollte also klassengebunden sein). Haben Sie einen Anwendungsfall dafür oder sind Sie nur neugierig? – Hamish

+0

Ich habe eine 'Klasse'' A', die eine 'delegate'' Eigenschaft' hat. Alle derzeitigen Delegierten sind Klassen. Jetzt habe ich einen Delegierten für eine neue Situation geschrieben, und als ich versuche, 'struct' gegenüber' class'es zu bevorzugen, wo immer ich kann, habe ich eine 'struct' implementiert, was für die anderen Delegierten nicht möglich ist (sie haben eine Identität). Aufgrund der Themenfrage musste ich es dann zu einer Klasse machen. – shallowThought

Verwandte Themen