2016-10-05 3 views
6

L'initialisation suivante produit actuellement cette erreur dans la ligne qui appelle getEventCalendar:Initialiser variable d'instance paresseuse avec une valeur qui dépend d'autres variables d'instance

Impossible d'utiliser membre d'instance « getEventCalendar » au sein de la propriété initialiseur; Les initialiseurs de propriétés sont exécutés avant que 'self' soit disponible.

Y at-il moyen approprié pour initialiser la variable d'instance lazy avec une valeur qui dépend de l'autre type d'objet instance variables de self (pas seulement selfalone)? J'ai par exemple essayé de transformer getEventCalendar d'une méthode dans une fonction, mais cela n'aide pas non plus.

class AbstractEventCalendarClient { 

    let eventStore: EKEventStore 
    let entityType: EKEntityType 

    lazy var eventCalendar = getEventCalendar() 

    init(eventStore: EKEventStore, entityType: EKEntityType) { 
    self.eventStore = eventStore 
    self.entityType = entityType 
    } 

    func getEventCalendar() -> EKCalendar? { 
    // ... 
    } 
} 
+2

connexes: http://stackoverflow.com/questions/38118429/swift-lazy-instantiating-using-self. –

Répondre

4

Vous pouvez utiliser une fermeture exécutée une seule fois qui capture les propriétés de self et les utiliser lors de l'exécution (= première utilisation de la propriété lazy). Par exemple.

class Foo { 
    var foo: Int 
    var bar: Int 
    lazy var lazyFoobarSum: Int = { return self.foo + self.bar }() 

    init(foo: Int, bar: Int) { 
     self.foo = foo 
     self.bar = bar 
    } 
} 

let foo = Foo(foo: 2, bar: 3) 
foo.foo = 7 
print(foo.lazyFoobarSum) // 10 

W.r.t. à votre propre initiative: vous pouvez, de la même manière, utiliser les fonctions help (instance) de self dans cette fermeture exécutée une seule fois.

class Foo { 
    var foo: Int 
    var bar: Int 
    lazy var lazyFoobarSum: Int = { return self.getFooBarSum() }() 

    init(foo: Int, bar: Int) { 
     self.foo = foo 
     self.bar = bar 
    } 

    func getFooBarSum() -> Int { return foo + bar } 
} 

let foo = Foo(foo: 2, bar: 3) 
foo.foo = 7 
print(foo.lazyFoobarSum) // 10 
+0

Oui, intelligent. J'utilise maintenant cette ligne textuelle: 'lazy var eventCalendar: EKCalendar? = {return self.getEventCalendar()}() '. – Drux

+0

@Drux: 'paresseux var eventCalendar: EKCalendar? = self.getEventCalendar() 'devrait aussi fonctionner, ce qui a été suggéré dans une réponse (maintenant supprimée) de @Hamish. –

+0

@Drux Notez que, comme Hamish l'a montré dans sa réponse (maintenant supprimée), vous n'avez pas besoin d'enrouler un tel appel de méthode d'instance dans une fermeture elle-même, mais simplement utiliser var paresseux eventCalendar: EKCalendar? = self.getEventCalendar() 'sans la fermeture. La méthode de fermeture peut être pratique si vous voulez inclure plus de logique dans l'instanciation paresseuse du 'eventCalender' (dans votre cas, cette logique est maintenant contenue dans la méthode' getEventCalender'). – dfri

2

C'est un message d'erreur confus (que vous pouvez bien vouloir file a bug report sur). Le problème est juste une bizarrerie de lazy propriétés - ils nécessitent actuellement une utilisation explicite de self afin d'accéder aux membres de l'instance, ainsi qu'une annotation de type explicite lors de ce faire (qui a été précédemment noté dans this Q&A).

Par conséquent, vous devez dire: (presque en double)

lazy var eventCalendar: EKCalendar? = self.getEventCalendar()