1. 线程安全(系统默认)
atomic
:
1.atomic
原子性指的是一个操作不可以被CPU中途暂停,然后再调度。即不能被中断,要么就执行完,要么就不执行
2.atomic
是自旋锁,Objc
使用的一种线程保护技术。当上一线程没有执行完毕的时候(被锁住),下一个线程会一直等待(不会进入睡眠状态),当上衣线程任务执行完毕,下一线程立即执行。它区别于互斥锁,互斥锁在等待的时候,会进入睡眠状态,当被上一线程执行完毕后,会被唤醒,然后再执行。
3.atomic
只给setter
方法上锁,getter
不会加锁
4.atomic
需要消耗大量的系统资源,执行效率低
nonatomic
:
非原子性,非线程安全,多个线程可以同时对其进行访问,使用该属性编译器会少生成加锁代码,提高性能和效率,使用频率高,一般都是放弃安全,提高性能所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,
nonatomic
是一个非常好的选择。
**2. 访问权限 **
readonly
:只读,所修饰的属性只有getter
readwrite
:读写,所修饰属性既有getter
又有setter
**3. 内存管理 **
1>、
assign
:
简单赋值,不更改索引计数;适用于基本数据类型:NSInterger、CGFloat和C数据类型 int、float等
2>、
strong
:和retain
:
相同点:都是针对对象类型进行内存管理。当给对象类型使用此修饰符时,setter
方法会先将旧的对象属性release
掉,再将新的对象赋值给属性并对该对象进行一次retain
操作,两者都会增加对象的引用计数。
不同点:strong
一般用于ARC环境,retain
用于MRC环境
3>、
assign
:和weak
:
相同点:都不牵扯到内存管理,也不会增加引用计数。
不同点:assign
既可修饰基本数据类型也可修饰OC对象;但如果修饰对象类型指向的是一个强指针,当它指向的这个指针释放后,它仍指向这块内存,必须手动给其置为nil
,否则就会产生野指针,如果还通过此指针操作那块内存,便会导致EXC_BAD_ACCESS错误,调用了已经释放的内存空间;
而weak
只能修饰OC对象,且相对assign
比较安全,如果指向的对象消失了,那么它会自动置为nil
,不会产生野指针。
弱引用除了不决定对象的存亡外,其他与强引用相同。即使一个对象被持有无数个若引用,只要没有强引用指向他,那麽其还是会被清除。
4>、
weak
:
弱引用除了不决定对象的存亡外,其它与强引用相同。即使一个对象被持有无数个弱引用,只要没有强引用指向它,还是会被清除。
从storyboard或xib上创建的控件,在控件放在view上的时候,就形成了如下的引用关系,以UIButton为例:
UIViewController->UIView->subView->UIButton
为这个UIButton声明一个weak属性
@property (nonatomic, weak) IBOutlet UIButton *btn;
// IBOutlet的属性一般可以设为weak是因为它已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。
//代理必须是weak,因为代理一般都是指向控制器,会造成循环引用,无法释放,造成内存泄露
5>、
copy
: 和strong
:
(1)strong
是强引用,指向的是同一个内存地址。
(2)copy
是为了减少对上下文的依赖而引入的机制,可以理解为内容的拷贝,会另外开辟内存空间,指针指向一个不同的内存地址,copy
返回的是一个不可变对象,如果使用strong
修饰可变对象,那么对象就会有可能被不经意间修改,有时不是我们想要的,而copy
不会发生这种意外。
(3)当用copy
修饰,setter
方法中会自动判断,如果来源是不可变的,那么和strong
一样,进行浅拷贝,会增加其引用计数;如果来源是可变的就进行深拷贝,不会增加其引用计数。
例:
@property (nonatomic, copy) NSString *coName;
@property (nonatomic, strong) NSString *stroName;
NSMutableString *mStr = [NSMutableString stringWithString:@"张三"];
self.coName = mStr;
self.stroName = mStr;
NSLog(@"用copy修饰第1次打印的值%@",self.coName);
NSLog(@"用strong修饰第1次打印的值%@",self.stroName);
[mStr appendString:@"风"];
/*
因为coName使用了copy修饰,mStr通过copy得到了一个新的对象赋值给self.coName,
这样再修改mStr就跟self.coName没关系了,只有直接对self.coName进行赋值才能改变它的值,
这样就保证了程序的封装性
*/
NSLog(@"用copy修饰第2次打印的值%@",self.coName);
NSLog(@"用strong修饰第2次打印的值%@",self.stroName);
打印结果:
用copy修饰第1次打印的值张三
用strong修饰第1次打印的值张三
用copy修饰第2次打印的值张三
用strong修饰第2次打印的值张三风
**4. 指定setter
和 getter
**
就是不用系统的
setter
和getter
,替换成自定义的函数
tips:
http://blog.csdn.net/qq_32744055/article/details/53443805
https://www.zhihu.com/question/20102376
https://www.jianshu.com/p/da797678ef95
https://www.zhihu.com/question/29927614?sort=created