Frage
In den Apple-Dokumenten wird Folgendes angegeben:
willSet- und didSet-Beobachter werden beim ersten Initialisieren einer Eigenschaft nicht aufgerufen. Sie werden nur aufgerufen, wenn der Wert der Eigenschaft außerhalb eines Initialisierungskontexts festgelegt wird.
Ist es möglich, diese während der Initialisierung aufzurufen?
Warum?
Nehmen wir an, ich habe diese Klasse
class SomeClass {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
init(someProperty: AnyObject) {
self.someProperty = someProperty
doStuff()
}
func doStuff() {
// do stuff now that someProperty is set
}
}
Ich habe die Methode erstellt doStuff
, um die Verarbeitungsaufrufe präziser zu gestalten, aber ich möchte lieber nur die Eigenschaft innerhalb der didSet
Funktion verarbeiten. Gibt es eine Möglichkeit, diesen Aufruf während der Initialisierung zu erzwingen?
Aktualisieren
Ich habe beschlossen, nur den Convenience-Intializer für meine Klasse zu entfernen und Sie zu zwingen, die Eigenschaft nach der Initialisierung festzulegen. Dadurch kann ich wissen, didSet
dass immer aufgerufen wird. Ich habe nicht entschieden, ob dies insgesamt besser ist, aber es passt gut zu meiner Situation.
defer
:convenience init(someProperty: AnyObject) { self.init() defer { self.someProperty = someProperty }
Antworten:
Erstellen Sie eine eigene Set-Methode und verwenden Sie diese in Ihrer Init-Methode:
quelle
someProperty
als Typ deklarierenAnyObject!
(ein implizit entpacktes optionales Element), können Sie dieself
vollständige Initialisierung durchführen, ohnesomeProperty
festgelegt zu werden. Wenn Sie anrufen, rufensetSomeProperty(someProperty)
Sie ein Äquivalent von anself.setSomeProperty(someProperty)
. Normalerweise können Sie dies nicht tun, daself
es nicht vollständig initialisiert wurde. DasomeProperty
keine Initialisierung erforderlich ist und Sie eine von abhängige Methode aufrufenself
, verlässt Swift den Initialisierungskontext unddidSet
wird ausgeführt.init() { *HERE* }
ist, didSet aufgerufen. Gut für diese Frage, aber die Verwendung einer sekundären Funktion zum Festlegen einiger Werte führt dazu, dass didSet aufgerufen wird. Nicht großartig, wenn Sie diese Setter-Funktion wiederverwenden möchten.Wenn Sie
defer
innerhalb eines initializer , für die Aktualisierung aller optionalen Eigenschaften oder ein weitere Aktualisierung nicht-optionale Eigenschaften , dass Sie bereits initialisiert haben und nach haben Sie genanntsuper.init()
Methoden, dannwillSet
,didSet
usw. genannt werden. Ich finde das bequemer als die Implementierung separater Methoden, mit denen Sie den Anruf an den richtigen Stellen verfolgen können.Beispielsweise:
Wird ergeben:
quelle
defer
. Vielen Dank.Als Variation von Olivers Antwort könnten Sie die Zeilen in einen Verschluss einwickeln. Z.B:
Edit: Brian Westphals Antwort ist imho schöner. Das Schöne an ihm ist, dass es auf die Absicht hinweist.
quelle
Ich hatte das gleiche Problem und das funktioniert bei mir
quelle
Dies funktioniert, wenn Sie dies in einer Unterklasse tun
Wird
a
beispielsweisedidSet
nicht ausgelöst. Wird aber zumb
BeispieldidSet
ausgelöst, weil es in der Unterklasse ist. Es hat etwas mit dem zu tun, wasinitialization context
wirklich bedeutet, in diesem Fall hat sich dassuperclass
darum gekümmertquelle
Dies ist zwar keine Lösung, aber eine alternative Vorgehensweise wäre die Verwendung eines Klassenkonstruktors:
quelle
someProperty
da sie bei der Initialisierung keinen Wert erhalten hat.In dem speziellen Fall, in dem Sie eine in Ihrer Oberklasse verfügbare Eigenschaft aufrufen
willSet
oderdidSet
in diese aufnehmen möchteninit
, können Sie Ihre Super-Eigenschaft einfach direkt zuweisen:Beachten Sie, dass die Charlesism- Lösung mit einem Verschluss in diesem Fall immer auch funktionieren würde. Meine Lösung ist also nur eine Alternative.
quelle
Sie können es auf folgende Weise lösen:
quelle
self.someProperty
Initialisierungsbereich verlassen , wenn Sie anrufen . Ich glaube, dass das Gleiche erreicht werden kannvar someProperty: AnyObject! = nil { didSet { ... } }
. Einige mögen es dennoch als Umgehungsmöglichkeit schätzen, danke für den Zusatz