iOS开发SwiftiOS进阶指南iOS开发记录

swift2.0下重写setter和getter

2015-12-16  本文已影响2852人  mmaoyudi

想必各位读者也都知道在oc下的点语法就是调用getter和setter方法,所以通过重写getter和setter方法可以在你给一个类的属性赋值的时候做一些处理,好让以后的操作更加方便,比如写一个UIVIew的分类,然后往里面加一个x属性

 @property(nonatomic.assign)CGFloat x;
//虽然在分类里面不能添加属性,但上面这句代码就等价于
-(void)setX:(CGFloat)x;
-(CGFloat)x;

//再在.m文件里重写getter和setter方法
-(void)setX:(CGFloat)x
{
 CGFrame    frame = self.frame;
frame.origin.x=x;
self.frame=frame;
}


-(CGFloat)x
{
return self.frame.origin.x;
}

/*这样在引入头文件后,设置一个控件的frame的时候就可以直接用点语法了,
因为控件的frame不可以直接给位置或大小赋值,只能重新赋一个frame给他
这样在控件多并且为之有改变,不用约束的情况下会很方便*/

/*
但以上方法在swift中的使用差距就会有点大了,那么我就先说一下我对swift的setter和getter方法的理解吧,首先swift里面已经没有了.m和.h文件,这样就不能通过@proerty来创建getter和setter方法了,虽然有set和get,不过它们不能给自己赋值,但可以通过它改变一些其它的值,总体来讲就是功能更强大了,那么我就先举个小例子
*/

//先实现和ocgeitter和setter一样的效果
//首先swift里的变量和常量,变量是var常量是let因为要重写,要重新赋值所以用var
//myd赋个空也可以""但不能什么也不写,会报错


var name  = "myd" {         /*这里是在赋值之前会调用,在这里面会有一个新属性newValue,这个newValue就等价与之前oc里面的-(void)setX:(CGFloat)x;里面最后面的那个小x这样你就可以处理新值了,并把他直接赋值给当前属性*/
willSet{
name = newValue
}                                   //这里就是在赋完值以后,马上就回进入,并不是当你需要取值的时候才会进到这里,但是这里面的name已经是改变以后的值了,所以当你对这里面的name进行一系列的操作时其实就和oc里面的重写get方法是一样的,只不过是直接改变属性本身的值,但效果都是一样的
 didSet{
name = name + "hhhh"
} }

//这样如果我们在给它赋值的时候就可以在willSet里面做很多操作,并且可以在didSet里面修改里面的值,来起到当我们再次调用这个属性的时候拿到的是修改后的值"mydhhhh"

以上是为了好理解而写的,下面是官方文档的解释

属性监视器
属性监视器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性监视器,甚至新的值和现在的值相同的时候也不例外。

可以为除了延迟存储属性之外的其他存储属性添加属性监视器,也可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性监视器。属性重载请参考继承一章的重载。

注意:不需要为无法重载的计算属性添加属性监视器,因为可以通过 setter 直接监控和响应值的变化。

可以为属性添加如下的一个或全部监视器:

willSet在设置新的值之前调用
didSet在新的值被设置之后立即调用
willSet监视器会将新的属性值作为固定参数传入,在willSet的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称newValue表示。

类似地,didSet监视器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue。

注意:willSet和didSet监视器在属性初始化过程中不会被调用,他们只会当属性的值在初始化之外的地方被设置时被调用。

这里是一个willSet和didSet的实际例子,其中定义了一个名为StepCounter的类,用来统计当人步行时的总步数,可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。

 class StepCounter { 
 var totalSteps: Int = 0 { 
 willSet(newTotalSteps) { 
    println("About to set totalSteps to \(newTotalSteps)") 
} 
didSet { 
    if totalSteps > oldValue  { 
        println("Added \(totalSteps - oldValue) steps") 
    } 
 } 
} 
} 
let stepCounter = StepCounter() 
stepCounter.totalSteps = 200 
// About to set totalSteps to 200 
// Added 200 steps 
stepCounter.totalSteps = 360 
// About to set totalSteps to 360 
// Added 160 steps 
stepCounter.totalSteps = 896 

// About to set totalSteps to 896 
// Added 536 steps 
StepCounter类定义了一个Int类型的属性totalSteps,它是一个存储属性,包含willSet和didSet监视器。

当totalSteps设置新值的时候,它的willSet和didSet监视器都会被调用,甚至当新的值和现在的值完全相同也会调用。

例子中的willSet监视器将表示新值的参数自定义为newTotalSteps,这个监视器只是简单的将新的值输出。

didSet监视器在totalSteps的值改变后被调用,它把新的值和旧的值进行对比,如果总的步数增加了,就输出一个消息表示增加了多少步。didSet没有提供自定义名称,所以默认值oldValue表示旧值的参数名。

注意:如果在didSet监视器里为属性赋值,这个值会替换监视器之前设置的值。

上一篇下一篇

猜你喜欢

热点阅读