@property都有哪些修饰词?以及作用总结

2018-03-03  本文已影响0人  塞北孤雁

常见的修饰词: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.使用注意:

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来确保线程的安全。

更准确的说应该是读写安全,但并不是线程安全的,因为别的线程还能进行读写之外的其他操作。线程安全需要开发者自己来保证。

上一篇 下一篇

猜你喜欢

热点阅读