Accéder à soi-même à partir des propriétés d’instance qui sont des fermetures

J’utilise Xcode6-beta2, mais j’ai eu le même problème depuis la toute première version bêta publique. Ma sous-classe Swift d’Obj-C UIViewController ressemble à ceci:

class SomeVC: UIViewController { var c1: () -> () = { println(self) } var c2: () -> () { get { return { println(self) } } } var c3: () -> () { return { println(self) } } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) c1() c2() c3() } } 

Lorsque le VC est affiché, je vois les lignes suivantes imprimées:

 (Function)   

(c2 et c3 ne diffèrent que par le fait qu’il n’est pas nécessaire d’inclure le get {…} pour une propriété calculée s’il n’est que

Ainsi, le self de la première fermeture semble se référer au type de fonction / fermeture lui-même, tandis que les autres se réfèrent au contrôleur de vue (comme on peut s’y attendre). La seule différence entre c1 et c2 / c3 est que la première est une propriété stockée, la seconde est une propriété calculée, mais je pense que les fermetures et leurs valeurs capturées seront identiques, c’est-à-dire que Dans l’état actuel des choses, la fermeture de c1 ne semble pas avoir de manière évidente d’accéder aux méthodes / propriétés de la classe englobante.

Est-ce quelque chose de documenté quelque part (j’ai lu le livre de Swift et je n’ai rien trouvé), ou est-ce juste un bug de bêta-compilateur, qui devrait être classé quelque part?

Cela semble intéressant. J’ai donc fait une enquête. Vous pouvez accéder aux variables d’instance de classe depuis la fermeture comme self.instanceVariable . À ce moment-là, la fermeture capturera le self en son sein. Alors maintenant, le self réfère à l’instance de classe elle-même. Votre fermeture devrait être une propriété paresseuse .

Une propriété paresseuse signifie que vous pouvez vous référer à self dans la fermeture par défaut, car la propriété paresseuse ne sera accessible qu’après la fin de l’initialisation et la connaissance de l’existence de self.

Vous manquez @lazy de sorte que self est inconnu à la fermeture, c’est pourquoi il l’imprime en tant que (Function) ma conjecture.

 class TableViewController: UIViewController { var name = "anil" // Since swift 2.0 came out @lazy is replaced by lazy lazy var c1: () -> () = { println(self) println(self.name) } var c2: () -> () { get { return { println(self) } } } var c3: () -> () { return { println(self) } } override func viewDidLoad() { super.viewDidLoad() c1() c2() c3() } } 

Sortie

<_ttc12tableviewapp19tableviewcontroller: 0x10d54e000>
anil
<_ttc12tableviewapp19tableviewcontroller: 0x10d54e000> <_ttc12tableviewapp19tableviewcontroller: 0x10d54e000>


Mettre à jour

L’atsortingbution d’une clôture à une variable d’instance de classe entraîne un cycle de référence fort. Vous devriez éviter cela. Swift utilise la liste de capture pour cela

Si vous affectez une fermeture à une propriété d’une instance de classe et que la fermeture capture cette instance en faisant référence à l’instance ou à ses membres, vous créerez un cycle de référence fort entre la fermeture et l’instance. Swift utilise des listes de capture pour briser ces forts cycles de référence. Pour plus d’informations, voir Cycles de référence forts pour les fermetures .

Donc, l’utilisation correcte de la fermeture pourrait être

 @lazy var c1: () -> () = { [unowned self] in println(self) println(self.name) } 

Référence: Guide de programmation rapide

modifier
@lazy a été changé en paresseux