Dzięki tej prostej klasie otrzymuję ostrzeżenie kompilatora
Próba modyfikacji / dostępu
x
w ramach własnego setera / gettera
a kiedy używam tego w ten sposób:
var p: point = Point()
p.x = 12
Dostaję EXC_BAD_ACCESS. Jak mogę to zrobić bez wyraźnego tworzenia kopii zapasowych?
class Point {
var x: Int {
set {
x = newValue * 2 //Error
}
get {
return x / 2 //Error
}
}
// ...
}
set
którego chcesz używaćdidSet
. Po wdrożeniu właściwości zachowują się inaczej w Swift niż Objective-C lub innych językachset
. Zobacz odpowiedź poniżej z @jack i przykładdidSet
z @cSquirrelOdpowiedzi:
Settery i Getters mają zastosowanie do
computed properties
; takie właściwości nie mają pamięci w instancji - wartość z gettera ma być obliczona na podstawie innych właściwości instancji. W twoim przypadku nie max
przypisania.Jawnie: „Jak mogę to zrobić bez wyraźnego tworzenia kopii zapasowych”. Nie można - trzeba coś do tworzenia kopii zapasowych nieruchomości komputerowej. Spróbuj tego:
W szczególności w Swift REPL:
źródło
Settery / gettery w Swift są zupełnie inne niż ObjC. Właściwość staje się własnością obliczoną, co oznacza, że nie ma zmiennej
_x
bazowej, takiej jak w ObjC.W poniższym kodzie rozwiązania widać, że
xTimesTwo
nic nie przechowuje, ale po prostu oblicza wynikx
.Zobacz oficjalne dokumenty dotyczące obliczonych właściwości .
Funkcjonalność, którą chcesz, może być również obserwatorem właściwości .
Potrzebujesz:
Możesz modyfikować inne właściwości w setter / getters, do czego są przeznaczone.
źródło
didSet
co pozwoli ci zmienić wartość natychmiast po jej ustawieniu. Nie ma jednak nic do zdobycia ...x
plecami dooldValue
wdidSet
. Ta zmiana w zachowaniu jest bardzo myląca, ponieważ pochodzi od właściwości Objective-C, dzięki!Można dostosować ustawioną wartość za pomocą obserwatora właściwości. Aby to zrobić, użyj „didSet” zamiast „set”.
Co do gettera ...
źródło
x
wartość domyślną w tym wzorcu?var x: Int = 0 { didSet { ...
.Aby rozwinąć odpowiedź na temat GoZonera:
Twoim prawdziwym problemem jest to, że rekurencyjnie dzwonisz do swojego gettera.
Jak sugeruje powyższy komentarz do kodu, nieskończenie wywołujesz moduł pobierający właściwość x, który będzie kontynuowany do momentu otrzymania kodu EXC_BAD_ACCESS (możesz zobaczyć pokrętło w prawym dolnym rogu środowiska zabaw Xcode).
Rozważ przykład z dokumentacji Swift :
Zauważ, że właściwość obliczona przez środek nigdy nie zmienia się ani nie zwraca siebie w deklaracji zmiennej.
źródło
get
. Ponieważ to uruchomiłoby inną,get
która uruchomiłaby inną. . . Nawet go nie drukuj. Ponieważ drukowanie wymaga również „uzyskania” wartości, zanim będzie można ją wydrukować!W celu zastąpienia
setter
igetter
dla szybkich zmiennych użyj poniższego koduMusimy zachować wartość zmiennej w zmiennej tymczasowej, ponieważ próba uzyskania dostępu do tej samej zmiennej, której getter / setter jest zastępowany, spowoduje nieskończone pętle.
Możemy przywołać setera w ten sposób
Getter zostanie wywołany przy odpaleniu poniżej podanego wiersza kodu
źródło
Jesteś rekursywnie definiowania
x
zx
. Jakby ktoś zapytał, ile masz lat? A ty odpowiadasz „Jestem dwa razy starszy”. Co nie ma sensu.Musisz powiedzieć, że jestem dwa razy starszy od Johna lub jakąkolwiek inną zmienną oprócz ciebie .
zmienne obliczane są zawsze zależne od innej zmiennej.
Zasadą kciuka jest, aby nigdy nie uzyskiwać dostępu do samej właściwości z poziomu gettera, tj
get
. Ponieważ to uruchomiłoby inną,get
która uruchomiłaby inną. . . Nawet go nie drukuj. Ponieważ drukowanie wymaga również „uzyskania” wartości, zanim będzie można ją wydrukować!To dałoby następujące ostrzeżenie:
Błąd wygląda niejasno:
Alternatywnie możesz użyć
didSet
. Dzięki temudidSet
uzyskasz wartość ustawioną wcześniej i dopiero ustawioną na. Aby uzyskać więcej, zobacz tę odpowiedź .źródło
Aktualizacja: Swift 4
W poniższej klasie seter i getter są stosowane do zmiennej
sideLength
Tworzenie obiektu
Rębacz
Seter
źródło
Spróbuj użyć tego:
Jest to w zasadzie odpowiedź Jacka Wu, ale różnica polega na tym, że w odpowiedzi Jacka Wu jego zmienna x jest
var x: Int
, w mojej, moja zmienna x jest taka:var x: Int!
więc wszystko, co zrobiłem, to uczynienie z niej opcjonalnego typu.źródło
Aktualizacja dla Swift 5.1
Począwszy od wersji Swift 5.1, możesz teraz uzyskać zmienną bez użycia słowa kluczowego get . Na przykład:
źródło
Settery i gettery w Swift dotyczą obliczonych właściwości / zmiennych. Te właściwości / zmienne nie są faktycznie przechowywane w pamięci, ale są obliczane na podstawie wartości przechowywanych właściwości / zmiennych.
Zobacz dokumentację Apple Swift na ten temat: Swift Variable Declarations .
źródło
Oto teoretyczna odpowiedź. Można to znaleźć tutaj
źródło