[问题]
折腾:
期间,需要去搞清楚,ivar和property的区别。
[折腾过程]
1.搜:
iOS ivar vs property
参考:
[总结]
ivar=instance variable,好理解:
类的每个实例对象都会存在的变量
-》
其他语言中,对于访问这种 实例变量 的做法,一般是:
设置对应的getter和setter,
比如,
一个car的stopSpeed,对应的getter和setter是:
getTopSpeed()和setTopSpeed()
Car.h:
![car header file](https://www.crifan.com/files/pic/uploads/2016/05/car-header-file.png)
Car.m:
![car implement m file](https://www.crifan.com/files/pic/uploads/2016/05/car-implement-m-file.png)
而property==属性变量
的出现是为了减少你为了写getter和setter的多写的那么些代码
-》为了不需要再去写(多余的)getter和setter
和上面等价的,用property的写法是:
Car.h:
![property car header file](https://www.crifan.com/files/pic/uploads/2016/05/property-car-header-file.png)
Car.m:
![property car implement m file](https://www.crifan.com/files/pic/uploads/2016/05/property-car-implement-m-file.png)
-》感觉像是 如果把ivar换成property的话,iOS自动就帮你内部实现了getter和setter。
-》iOS根据你的指定 @synthesize 后,会自动帮你处理getter和setter
-》当然,除了标准的getter和setter之外,如果你有需要自定义的处理,则可以重写getter和setter即可。
提示:
当你用
@property (和@synthesize)
(或者叫做:@synthesize a @property==合成一个属性?)
去修饰一个变量的话,则该属性则会自动地创建实例对象的变量,不过会加上一个下划线前缀。
-》所以此处对于:
@property (nonatomic) int topSpeed;
系统还会自动创建一个名为_topSpeed的实例的变量
-》Object-C 2.0之前,是需要自己手动创建getter和setter的
-》并且,也是有多种方式,多种选择,去创建对应的getter和setter
-》所以你也会看到不止一种方式去声明@property
-》如果你不打算自定义的话,则不需要自己重写getter和setter了,而是直接用系统内部自动生成的getter和setter就可以了。
看起来,直接用property,就好像可以完全取代ivar了,而ivar完全不需要了?
也不是,因为:
如果你想要创建,不允许别人访问的,私有变量的话,则还是用ivar比较好
其他情况的话,还是用property更好。
---》》》
此时,基本清楚了:
如果想要实现实例的私有变量,则最好用ivar
否则,用property比较好-》自动生成getter和setter,并且自动生成一个加了下划线前缀的ivar
所以,其实可以看成是:
- ivar==仅仅只是个变量
- property==(系统自动生成了)操作变量的(单个/或两个)函数myProperty和setMyProperty
ivar:是必须存在的
property:是可选的。虽然推荐使用,也很好用。
-》你的类,可以有ivar没property,但是不能只有property而没ivar
-》好像只有一个特例:category中的只读属性
-》property是(iPhone第一次发布时)OC 2.0之后引入的
-》有20多年之前的很多旧代码中,是没有propety的。
你不必显示地定义ivar
-》不代表你不需要定义ivar
-》有时候只不过是系统帮你定义了,但是你要知道背后发生了什么
就像这种:
@interface MyObject: NSObject
{
NSArray *array;
}
@property (nonatomic, strong) NSArray *array;
可以写成这种:
@interface MyObject: NSObject
{
}
@property (nonatomic, strong) NSArray *array;
实际上ivar是存在的,只不过没有强制你显示地去定义而已。
声明了
@property
并@synthesize
后编译器会为你的实例变量生成getter和setter,这些方法会遵循你声明的内存管理的语义,在set的时候执行对应的操作,比如retain
,copy
等;但它们是方法,而不是变量,所以obj.foo = @"a"
其实是一个语法糖,等同于[obj setFoo:@"a"]
。在过去你还需要声明对应的实例变量,并通过@synthesize foo = _foo
的方式建立和它们之间的关系,但新的Clang编译器会默认帮你加入@synthesize
的步骤,默认实例变量形式为property名加下划线。但是你依然可以声明实例变量,并手动建立和property的关系,尤其是实例变量的形式与默认的不同,比如:@synthesize foo = _bar
。一般的情况下你应该多用@property,因为它可以进行某种程度的自动内存管理(根据你声明时的语意义),但是由于getter和setter本质上是普通的方法,所以它们可以被覆盖,可以执行除了get和set额外的操作(副作用),所以在某些情况下(比如init…和dealloc方法里)你会手动去进行赋值。
同理,由于@property声明的是方法,你可以不必有对应的实例变量,而是自行实现一个getter和setter执行自定义的操作。有时候你甚至不用去声明对应的实例变量和getter/setter,因为它们在父类已经存在,或者在运行时才存在,那么这时候你会用到
@dynamic
而不是@synthesize
,不然编译器会报错。关于使用实例变量还是@property,其实和用不用ARC没有太多关系。。。,它们也不是互相替代的关系