Я розумію, що встановлення та отримання призначені для обчислених властивостей (немає резервного копіювання із збережених властивостей )
якщо ви приїжджаєте від Objective-C, маючи на увазі, що конвенції про іменування змінилися. У Swift змінна iVar або екземпляр називається збереженою властивістю
Приклад 1 (лише властивість читання) - з попередженням:
var test : Int {
get {
return test
}
}
Це призведе до попередження, оскільки це призводить до рекурсивного виклику функції (сам виклик дзвонить). Попередження в цьому випадку - "Спроба змінити" тест "в межах власного геттера".
Приклад 2. Умовне читання / запис - з попередженням
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
}
}
}
Аналогічна проблема - ви не можете цього зробити, оскільки це рекурсивно викликає сетер. Крім того, зверніть увагу, що цей код не поскаржиться на відсутність ініціалізаторів, оскільки немає збереженого властивості для ініціалізації .
Приклад 3. читання / запис обчисленої властивості - із резервним сховищем
Ось схема, яка дозволяє умовно встановити фактично збережені властивості
//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
}
}
}
Примітка . Фактичні дані називаються _test (хоча це можуть бути будь-які дані або комбінація даних). Зауважте також, що потрібно надати початкове значення (альтернативно вам потрібно використовувати метод init), оскільки _test насправді є змінною екземпляра
Приклад 4. Використовуючи встановлений заповіт і зроблено
//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
}
}
}
Тут ми бачимо, що WillSet і didSet перехоплюють зміни фактично збереженої властивості. Це корисно для надсилання сповіщень, синхронізації тощо ... (див. Приклад нижче)
Приклад 5. Бетонний приклад - контейнер 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
}
}
}
Зверніть увагу на використання обчислених та збережених властивостей BOTH. Я використав обчислюване властивість, щоб запобігти встановленню одного і того ж значення двічі (щоб уникнути поганих речей!); Я використовував willSet і didSet для пересилання сповіщень для перегляду контролерів (див. Документацію UIViewController та інформацію про контейнери viewController)
Я сподіваюся, що це допомагає, і, будь ласка, хтось кричить, якщо я десь тут помилився!
get
&set
) властивість обчислюється на основі іншої властивості, наприклад, перетворення міткиtext
в рікInt
.didSet
&willSet
є, щоб сказати ... ей це значення було встановлено, тепер давайте зробимо це, наприклад, наш ресурс даних був оновлений ... тому давайте перезавантажимо tableView, щоб воно включало нові рядки. Інший приклад дивіться у відповіді dfri про те, як викликати делегатівdidSet