点语法
点语法是对属性的访问,经过oc消息派发,可以完成属性所定义的“内存管理语义”, 包含set和get方法。
下划线
下划线直接访问实例变量,不经消息派发访问速度更快,不会调用set和get方法,不会触发KVO。
注意点
1、懒加载,必须通过下划线来访问变量
2、不要在init和dealloc中使用点语法
对于 iOS 开发而言,直接使用成员变量效率会优于使用属性,但是直接使用成员变量也有不足之处:对于一个基本类型的变量(double, int)来说确实方便。但对于一个对象来说情况就复杂了,对象是 retain 呢还是 copy 呢?对于直接用成员变量来说,没有给出任何明确地行为,这往往会带来内存方面的问题。另外,如果这样直接的赋值,也不会触发 KVO。
使用点语法是更好的选择,因为这样可以兼容懒加载,同时也避免了使用下滑线的时候忽略了self这个指针,后者容易在block中造成循环引用,同时使用下划线是获取不到父类的属性,因为它只是对局部变量的访问。
所以说我们应该结合起来去使用成员变量和点语法。对于基本数据类型,直接使用成员变量;对于一个 OC 对象,我们在只读操作的时候,直接使用成员变量即可。而在读写操作的时候,用点语法即可。这样一来既避免了内存问题,KVO问题,也尽可能的提高了效率。
小知识:自动合成属性实例变量之后,@synthesize使用场景
1.同时重写了 setter 和 getter 时
2.重写了只读属性的 getter 时
3.使用了 @dynamic 时
4.在 @protocol 中定义的所有属性
5.在 category 中定义的所有属性
6.重载的属性
小知识:懒加载
懒加载,亦叫延迟加载,即在第一次需要的时候才去加载,本质上就是对一个实例的getter方法的重写。
懒加载的优点
相对来说,如果代码量不是很多,可读性略强;相对来说,防止为nil,减少了后续使用时安全检查的后顾之忧,使用适当,可节省内存资源。
懒加载的缺点
使用太泛滥,导致可读性变差,使用不得当,可能会造成死循环,导致crash,代码量增多。
注意:在懒加载中,用下划线方法,避免死循环。
后记:
@property(copy,nonatomic) NSString *aCopyMStr;
NSMutableString *mstrOrigin = [[NSMutableString alloc] initWithString:@"mstrOriginValue"];
_aCopyMStr= mstrOrigin;
NSLog(@"mstrOrigin输出:%p,%@\n", mstrOrigin,mstrOrigin);
NSLog(@"aCopyMStr输出:%p,%@\n",_aCopyMStr,_aCopyMStr);
NSLog(@"引用计数%@",[mstrOrigin valueForKey:@"retainCount"]);
2018-11-06 15:21:46.407712+0800 OC-Swift[7127:192355] mstrOrigin输出:0x60000301e850,mstrOriginValue
2018-11-06 15:21:46.407892+0800 OC-Swift[7127:192355] aCopyMStr输出:0x60000301e850,mstrOriginValue
2018-11-06 15:21:46.408095+0800 OC-Swift[7127:192355] 引用计数2
2018-11-06 15:27:50.202765+0800 OC-Swift[7169:194363] mstrOriginValueTest===mstrOriginValueTest
@property(copy,nonatomic) NSString *aCopyMStr;
NSMutableString *mstrOrigin = [[NSMutableString alloc] initWithString:@"mstrOriginValue"];
self.aCopyMStr= mstrOrigin;
NSLog(@"mstrOrigin输出:%p,%@\n", mstrOrigin,mstrOrigin);
NSLog(@"aCopyMStr输出:%p,%@\n",self.aCopyMStr,self.aCopyMStr);
NSLog(@"引用计数%@",[mstrOrigin valueForKey:@"retainCount"]);
[mstrOrigin appendString:@"Test"]; NSLog(@"%@===%@",mstrOrigin,self.aCopyMStr);
2018-11-06 15:22:07.847314+0800 OC-Swift[7127:192355] mstrOrigin输出:0x60000301e850,mstrOriginValue
2018-11-06 15:22:07.847502+0800 OC-Swift[7127:192355] aCopyMStr输出:0x600003019920,mstrOriginValue
2018-11-06 15:22:07.847629+0800 OC-Swift[7127:192355] 引用计数1
2018-11-06 15:33:53.367396+0800 OC-Swift[7258:198057] mstrOriginValueTest===mstrOriginValue
可见下划线只是访问实例变量,没有完成属性所定义的“内存管理语义”,这会带来内存方面的问题。当属性为copy时,需要用点语法调用属性才会对对象进行深拷贝,而下划线是指针指向相同的内存地址。
网友评论