Pytanie
Dokumenty Apple'a określają, że:
Obserwatory willSet i didSet nie są wywoływane przy pierwszej inicjalizacji właściwości. Są wywoływane tylko wtedy, gdy wartość właściwości jest ustawiona poza kontekstem inicjalizacji.
Czy można wymusić ich wywoływanie podczas inicjalizacji?
Czemu?
Powiedzmy, że mam tę klasę
class SomeClass {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
init(someProperty: AnyObject) {
self.someProperty = someProperty
doStuff()
}
func doStuff() {
// do stuff now that someProperty is set
}
}
Stworzyłem metodę doStuff
, aby wywołania przetwarzania były bardziej zwięzłe, ale wolałbym po prostu przetworzyć właściwość w ramach didSet
funkcji. Czy istnieje sposób, aby zmusić to do wywołania podczas inicjalizacji?
Aktualizacja
Postanowiłem po prostu usunąć wygodny interializer dla mojej klasy i zmusić cię do ustawienia właściwości po inicjalizacji. To pozwala mi wiedzieć, didSet
że zawsze będzie dzwonić. Nie zdecydowałem, czy jest to ogólnie lepsze, ale dobrze pasuje do mojej sytuacji.
defer
:convenience init(someProperty: AnyObject) { self.init() defer { self.someProperty = someProperty }
Odpowiedzi:
Utwórz własną metodę zestawu i użyj jej w metodzie init:
źródło
someProperty
jako typ:AnyObject!
(domyślnie nieopakowane opcjonalne), pozwalaszself
na pełną inicjalizację bezsomeProperty
ustawiania. Kiedy dzwoniszsetSomeProperty(someProperty)
, dzwonisz do równowartościself.setSomeProperty(someProperty)
. Zwykle nie byłbyś w stanie tego zrobić, ponieważself
nie został w pełni zainicjowany. PonieważsomeProperty
nie wymaga inicjalizacji i wywołujesz metodę zależną odself
, Swift opuszcza kontekst inicjalizacji ididSet
uruchamia się.init() { *HERE* }
będzie miało wywołanie didSet. Idealne do tego pytania, ale użycie dodatkowej funkcji do ustawienia niektórych wartości prowadzi do wywołania didSet. Nie wspaniale, jeśli chcesz ponownie użyć tej funkcji.Jeśli używasz
defer
wewnątrz z inicjatora , w celu aktualizacji opcjonalnych właściwości lub dalszej aktualizacji non-opcjonalne właściwości, które zostały już zainicjowane i po tym, jak nazywa się żadnychsuper.init()
metod, wówczaswillSet
,didSet
itp zostanie wywołana. Uważam, że jest to wygodniejsze niż wdrażanie osobnych metod, które musisz śledzić w odpowiednich miejscach.Na przykład:
Przyniesie:
źródło
defer
. Dzięki.Jako wariant odpowiedzi Olivera możesz zawinąć linie w zamknięcie. Na przykład:
Edycja: Odpowiedź Briana Westphala jest ładniejsza imho. Zaletą jego jest to, że wskazuje to na intencję.
źródło
Miałem ten sam problem i to działa dla mnie
źródło
Działa to, jeśli zrobisz to w podklasie
Na
a
przykładdidSet
nie jest wyzwalany. Ale nab
przykładdidSet
jest wyzwalany, ponieważ znajduje się w podklasie. To ma coś wspólnego z tym, coinitialization context
naprawdę oznacza, w tym przypadku osuperclass
to dbałoźródło
Chociaż nie jest to rozwiązanie, alternatywnym sposobem obejścia tego problemu byłoby użycie konstruktora klasy:
źródło
someProperty
ponieważ nie dałoby jej wartości podczas inicjalizacji.W szczególnym przypadku, w którym chcesz wywołać właściwość dostępną w nadklasie
willSet
lubdidSet
wewnątrzinit
niej, możesz po prostu przypisać swoją super właściwość bezpośrednio:Zauważ, że rozwiązanie Charlesism z zamknięciem zawsze działałoby również w tym przypadku. Więc moje rozwiązanie jest tylko alternatywą.
źródło
Możesz to rozwiązać w obj-с sposób:
źródło
self.someProperty
, opuszczasz zakres inicjalizacji. Wierzę, że to samo można osiągnąć, robiącvar someProperty: AnyObject! = nil { didSet { ... } }
. Mimo to niektórzy mogą docenić to jako obejście, dzięki za dodanie