实例变量增加了私有属性的设置,同时直接使用实例变量比使用属性的方式提高了运行速度。
Features
iVar变量介绍
这里首先认为大家都对Runtime有了一定的了解,不清楚的建议看看 南峰子的技术博客 。
还是稍微介绍下Ivar的的结构,Ivar其实是一个结构体指针:
再来查看这个结构体的结构:
输出所有的iVar的值
首先定义一个类,包含几个属性以及变量的值:
@interface Model : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end
同时在extension中生命iVar变量:
@interface Model () {
@private
int _value;
NSString *_title;
}
@end
输出的方式如下:
输出:
Type Encodings可参考 Objective-C Runtime Programming Guide
使用Runtime修改iVar的值
对于iVar的值,相当于私有属性,外部是无法访问的。不过在Runtime面前,一切都是小小case。
在外部可以通过runtime的方法来修改他:
可以给Model类暴露个打印的方法,在修改完数值之后调用方法观察数值是否发生了改变。
对于上面方法的原型:
俩参数为id,所以不能对基本类型做修改,可以通过偏移量的方式来获取,修改的方式如下:
这样我们就能随心所欲的修改各种变量的值了。
iVar vs Property
现在声明的属性,如果没有声明为dynamic,默认都是synthesize的。也就是会自动合成iVar变量。
那什么时候使用属性,什么时候直接使用实例变量呢?
首先要了解通过属性的方式来设置,其实内部还是设置实例变量的方式,无非是多了自己对象的判断以及对于引用计数的管理。所以直接访问实例变量的方式要快一些。
下面给出几种参考:
-
如果一个对象在它的生命周期中只在 alloc & init 时对引用计数做了 retain 操作,可直接使用实例变量的方式。
-
如果一个对象经常改变,使用属性的方式,而且使用点语法的方法进行访问(在本身的 getter & setter * dealloc & initializers 等方法里使用实例变量)。
-
私有变量的方式可以通过 extension 的方法,在 .m 文件里声明;暴露出去的方法需要在 .h 文件中以属性的方式来声明。
-
某些通过 setter & getter 方法访问的情形,只能使用属性。比如通过懒加载的方式来进行某些优化,设置观察者等等。
-
通过某些方法访问属性的时候,比如增加 KVC 的 KeyPath,一般通过他的 getter 方法,使用为 NSStringFromSelector(@selector(isFinished)) 来访问, 而非直接设置 isFinished 的方式。
比如生命一个 NSMutableArray, 基本不对他的引用计数做修改,只是使用它做些存储操作,可直接使用实例变量。
参考
- Stack Overflow - Must every ivar be a property?
- Stack Overflow - Why would you use an ivar?
- 0xBBC - Objective-C Runtime - Ivar