Rozumiem, że set i get są dla obliczonych właściwości (brak kopii zapasowej z przechowywanych właściwości )
jeśli pochodzisz z Celu-C, pamiętaj, że zmieniły się konwencje nazewnictwa. W Swift zmienna iVar lub zmienna instancji nosi nazwę właściwości przechowywanej
Przykład 1 (właściwość tylko do odczytu) - z ostrzeżeniem:
var test : Int {
get {
return test
}
}
Powoduje to ostrzeżenie, ponieważ powoduje rekurencyjne wywołanie funkcji (sam getter wywołuje sam). Ostrzeżenie w tym przypadku to „Próba zmodyfikowania„ testu ”we własnym getterze”.
Przykład 2. Warunkowy odczyt / zapis - z ostrzeżeniem
var test : Int {
get {
return test
}
set (aNewValue) {
//I've contrived some condition on which this property can be set
//(prevents same value being set)
if (aNewValue != test) {
test = aNewValue
}
}
}
Podobny problem - nie możesz tego zrobić, ponieważ rekurencyjnie wywołuje setera. Pamiętaj też, że ten kod nie będzie narzekał na brak inicjatorów, ponieważ nie ma przechowywanej właściwości do inicjalizacji .
Przykład 3. odczyt / zapis obliczonej właściwości - z zapleczem
Oto wzorzec, który umożliwia warunkowe ustawienie rzeczywistej przechowywanej właściwości
//True model data
var _test : Int = 0
var test : Int {
get {
return _test
}
set (aNewValue) {
//I've contrived some condition on which this property can be set
if (aNewValue != test) {
_test = aNewValue
}
}
}
Uwaga Rzeczywiste dane nazywa się _test (chociaż mogą to być dowolne dane lub kombinacja danych). Należy również zwrócić uwagę na potrzebę podania wartości początkowej (alternatywnie musisz użyć metody init), ponieważ _test jest w rzeczywistości zmienną instancji
Przykład 4. Korzystanie z will i did set
//True model data
var _test : Int = 0 {
//First this
willSet {
println("Old value is \(_test), new value is \(newValue)")
}
//value is set
//Finaly this
didSet {
println("Old value is \(oldValue), new value is \(_test)")
}
}
var test : Int {
get {
return _test
}
set (aNewValue) {
//I've contrived some condition on which this property can be set
if (aNewValue != test) {
_test = aNewValue
}
}
}
Widzimy tutaj willSet i didSet przechwytujące zmianę w rzeczywistej przechowywanej właściwości. Jest to przydatne do wysyłania powiadomień, synchronizacji itp. (Patrz przykład poniżej)
Przykład 5. Konkretny przykład - Kontener ViewController
//Underlying instance variable (would ideally be private)
var _childVC : UIViewController? {
willSet {
//REMOVE OLD VC
println("Property will set")
if (_childVC != nil) {
_childVC!.willMoveToParentViewController(nil)
self.setOverrideTraitCollection(nil, forChildViewController: _childVC)
_childVC!.view.removeFromSuperview()
_childVC!.removeFromParentViewController()
}
if (newValue) {
self.addChildViewController(newValue)
}
}
//I can't see a way to 'stop' the value being set to the same controller - hence the computed property
didSet {
//ADD NEW VC
println("Property did set")
if (_childVC) {
// var views = NSDictionaryOfVariableBindings(self.view) .. NOT YET SUPPORTED (NSDictionary bridging not yet available)
//Add subviews + constraints
_childVC!.view.setTranslatesAutoresizingMaskIntoConstraints(false) //For now - until I add my own constraints
self.view.addSubview(_childVC!.view)
let views = ["view" : _childVC!.view] as NSMutableDictionary
let layoutOpts = NSLayoutFormatOptions(0)
let lc1 : AnyObject[] = NSLayoutConstraint.constraintsWithVisualFormat("|[view]|", options: layoutOpts, metrics: NSDictionary(), views: views)
let lc2 : AnyObject[] = NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: layoutOpts, metrics: NSDictionary(), views: views)
self.view.addConstraints(lc1)
self.view.addConstraints(lc2)
//Forward messages to child
_childVC!.didMoveToParentViewController(self)
}
}
}
//Computed property - this is the property that must be used to prevent setting the same value twice
//unless there is another way of doing this?
var childVC : UIViewController? {
get {
return _childVC
}
set(suggestedVC) {
if (suggestedVC != _childVC) {
_childVC = suggestedVC
}
}
}
Zwróć uwagę na użycie OBA obliczonych i przechowywanych właściwości. Użyłem obliczonej właściwości, aby zapobiec dwukrotnemu ustawianiu tej samej wartości (aby uniknąć złych rzeczy!); Użyłem willSet i didSet do przekazywania powiadomień do viewControllers (zobacz dokumentację UIViewController i informacje o kontenerach viewController)
Mam nadzieję, że to pomoże, i proszę, niech ktoś krzyknie, jeśli popełniłem błąd tutaj!
get
&set
) polega zasadniczo na obliczeniu właściwości na podstawie innej właściwości, np. Konwersji etykiettext
na rokInt
.didSet
iwillSet
czy możemy powiedzieć ... hej, ta wartość została ustawiona, teraz zróbmy to, np. Nasze źródło danych zostało zaktualizowane ... więc przeładujmy tableView, aby zawierał nowe wiersze. Aby zobaczyć inny przykład, zobacz odpowiedź dfri na temat dzwonienia do delegatówdidSet