我的理解是 set 和 get 用于 computed properties(没有来自 stored properties 的支持)
如果您来自 Objective-C,请记住命名约定已经改变。在 Swift 中,一个 iVar 或实例变量被命名为 stored property
示例 1(只读属性) - 带有警告:
var test : Int {
get {
return test
}
}
这将导致警告,因为这会导致递归函数调用(getter 调用自身)。这种情况下的警告是“尝试在其自己的 getter 中修改 '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
}
}
}
类似的问题 - 你不能这样做,因为它递归地调用 setter。
另外,请注意此代码不会抱怨没有初始化程序,因为没有要初始化的存储属性。
示例 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. 使用 will 和 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
}
}
}
这里我们看到 willSet 和 didSet 拦截了实际存储属性的变化。
这对于发送通知、同步等很有用...(请参见下面的示例)
示例 5. 具体示例 - ViewController Container
//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
}
}
}
注意计算和存储属性的使用。我使用了一个计算属性来防止两次设置相同的值(以避免发生坏事!);我使用 willSet 和 didSet 将通知转发到 viewControllers(请参阅 UIViewController 文档和有关 viewController 容器的信息)
我希望这会有所帮助,如果我在这里的任何地方都犯了错误,请大喊大叫!