常见的修饰词:assign,weak,strong,retain,copy,nontomic,atomic,readonly,readwrite
assign(ARC/MRC)
1.这个修饰词是直接赋值的意思,整型、浮点型等基础数据类型都用该修饰词
2.如果没有使用weak、strong、retain、copy等词修饰,默认就用assign修饰(他们之间是有你没我的关系,一般的指针类型都用strong修饰)
3.当然其实对象也可以用assign修饰,只是对象的计数器不会加1.(与strong的区别)
4.如果用来修饰对象属性 , 那么当对象被销毁后指针是不会指向 nil 的 . 所以会出现野指针错误 ( 与weak的区别 )。
weak(ARC)(对象)
1.weak弱指针,修饰对象的修饰词,也就是说它不能修饰基本数据类型(int、float)
2.weak修饰的对象引用计数器不会加1,也就是直接赋值
3.弱引用是为打破引用循环而生的
4.它最被人所喜欢的原因是 它所指向的对象如果被销毁 , 它会指向 nil . 从而不会出现野指针错误 。
weak 和 assign的区别
assign和weak,他们都是弱引用类型,但是他们有区别的:
1.用weak声明的变量在栈中会被自动清空,赋值为nil;
2.用assign声明的变量在栈中可能不会被赋值为nil,就会造成野指针错误;
以delegate为例,在MRC中delegate被声明为assign,这是为了不造成循环引用,这时我们需要在dealloc中写上self.delegate = nil;
以免造成delegate的野指针错误,当然在ARC中只需要用weak声明delegate就可以自动释放了;
strong(ARC)(对象)
1.直接赋值,并且对象的引用计数器加1;
2.在ARC中替代了retain的作用;
retain(MRC)
1.release旧对象(旧对象计数器-1),retain新对象(新对象计数器+1),然后指向新对象
2.在set方法里面是这样写的:
if(_dog!=nil){
[_dog release]
}
_dog = [dog retain];
copy (ARC/MRC)
必须要使用copy的情况:(1.属性是一个不可变对象,如NSString,NSArray,NSDictionry;2.需要把一个可变对象赋值给属性,如把一个NSMutableString赋值给属性NSString,除此之外的情况的使用copy和strong是没区别的);
1.copy在MRC中时是这样做的:release旧对象,旧对象引用计数器减1,retain新对象新对象的引用计数器加1,然后指向新对象(新对象是最终指向的那个对象,不管是深拷贝还是浅拷贝)。在set方法里这样写的
if(_dog!=nil){
[_dog release]
}
_dog = [dog copy];
2.copy在ARC中是这样干的,copy新对象,新对象的引用计数器加1,然后指向新对象。在set方法里是这样写的:
_dog = [dog copy];
3.使用注意:
- 修饰的属性本身必须是不可变的。例如:NSMutableArray采用copy修饰,在addObject时会出现Crash,因为NSMutableArray的对象在copy时就会变成NSArray,如需要拷贝NSMutableArray对象用mutableCopy。
- 遵守NSCopying协议的对象使用
nonatomic(ARC/MRC)
1.不对set、get方法加同步锁
2.性能好
3.线程不安全
atomic(ARC/MRC)
1.原子属性就是对生成的set方法加互斥锁(互斥锁是一种同步锁,互斥锁:如果共享数据已经有其他线程加锁了,线程会进入休眠状态等待锁,一旦被访问的资源解锁,则等待访问资源的线程会被唤醒。自旋锁:如果共享的数据已经有其他线程加锁了,线程会以死循环的方式等待锁,一旦被访问的资源被解锁,则等待资源的线程会立即执行。自旋锁的效率高于互斥锁)
@synchronized(锁对象) 。
@synchronized(self) { _delegate = delegate;}
2.需要消耗系统资源
3.互斥锁是用线程同步实现的,意在保证同一时间只有一个线程调用set、set方法。
nonatomic和atomic的介绍和区别
当使用atomic时,虽然对属性的读和写是原子性的,但是仍然可能出现线程错误:当线程A进行写操作,这时其他线程的读或者写操作会因为等该操作而等待。当A线程的写操作结束后,B线程进行写操作,所有这些不同线程上的操作都将依次顺序执行——也就是说,如果一个线程正在执行 getter/setter,其他线程就得等待。如果有线程C在A线程读操作之前release了该属性,那么还会导致程序崩溃。所以仅仅使用atomic并不会使得线程安全,我们还要为线程添加lock来确保线程的安全。
更准确的说应该是读写安全,但并不是线程安全的,因为别的线程还能进行读写之外的其他操作。线程安全需要开发者自己来保证。
网友评论