@property是什么
@Property是声明属性的语法,它可以快速方便的为实例变量创建存取器,并允许我们通过点语法使用存取器。
存取器(accessor):指用于获取和设置实例变量的方法。用于获取实例变量值的存取器是getter,用于设置实例变量值的存取器是setter。
@property 后面可以有哪些修饰符
@property有10种属性修饰符可分为三大类。
一.原子性
1.atomic(默认):
a.atomic意为操作是原子的,意味着只有一个线程访问实例变量。
b.atomic是线程安全的,至少在当前的存取器上是安全的。
c.因为比较影响效率,在非ARC编译环境下,需要设置访问锁来保证对该变量进行正确的get/set,所以不常用。
2.nonatomic:
a.nonatomic跟atomic刚好相反。表示非原子的,可以被多个线程访问。
b.它是非线程安全型,访问速度快。
c.但不能保证在多线程环境下的安全性,当两个不同的线程对其访问时,容易失控。
总结:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:
if (property != newValue) {
[property release];
property = [newValue retain];
}
二.存取器控制
3.readwrite(默认):readwrite是默认值,表示该属性同时拥有setter和getter。
4.readonly: readonly表示只有getter没有setter。
三. 内存管理
5.assign(默认):
a.简单赋值,不更改索引计数。
假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b。此时a 和b指向同一块内存,请问当a不再需要这块内存,能否直接释放它?答案是否定的,因为a并不知道b是否还在使用这块内存,如果a释放了,那么b在使用这块内存的时候会引起程序crash掉。
b.适用简单数据类型,如int、float、double和NSInteger,CGFloat等表示单纯的复制。还包括不存在所有权关系的对象,比如常见的delegate。
- copy
用于非共享内存时,每个指针有自己的内存空间。也就是说实例变量是对传入对象的副本拥有所有权,而非对象本身。故修改copy的变量,对其他变无影响。
7.strong
a.ARC中默认属性,等于非ARC中的retain
b.实例变量对传入的对象要有所有权关系,即强引用。strong跟retain的意思相同并产生相同的代码,但是语意上更好更能体现对象的关系。
举个例子,当我们把指向一只风筝的变量声明为strong时,此时,你就拥有控制这只风筝的线,假如此时有五个人同时控制这只风筝(即这只风筝对象有三个strong类型的变量指向它),那么只有一种情况,这只风筝才会挣脱掉线的束缚:这三个人都放掉手中的线,(release掉)
8.weak
a.assign 相对应
b.用于IBOutlets,如,UIViewController的子类,即一般的控件。
c.在setter方法中,需要对传入的对象不进行引用计数加1的操作。
简单来说,就是对传入的对象没有所有权,当该对象引用计数为0时,即该对象被释放后,用weak声明的实例变量指向nil,即实例变量的值为0。
继续上面的例子,当我们把指向一只风筝的变量声明为weak时,此时,就像站在旁边看风筝的观众们一样,当上面的三个人还握着手中的线时,他们只能看到风筝,并不能控制它,他们能做的只能是用手指指向风筝,并大喊,“看,那只风筝飞得真高!”,然而,当上面的三个人把手中的线都放掉时,此时,风筝飞走了,看不见了,不管有再多的观众,他们再也看不到风筝了,这个故事告诉我们一个道理:当strong类型的指针被释放掉之后,所有的指向同一个对象的weak指针都会被清零。
9.retain:
a.在setter方法中,需要对传入的对象进行引用计数加1的操作。
简单来说,就是对传入的对象拥有所有权,只要对该对象拥有所有权,该对象就不会被释放。
b.与strong相对应,使用了引用计数,retain+1,release -1;当引用 计数为0时,dealloc会被调用,内存被释放
10.unsafe_unretauined
用在ARC编译环境下,在此环境下,与assign相似。它只是告诉ARC如何正确地调用声明为unsafe_unretauined变量的retain和release
属性相关问题
1.什么情况使用 weak 关键字,相比 assign 有什么不同?
a.在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性
b.自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义 IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。
c.weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似,然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。而 assign 的“设置方法”只会执行针对“纯量类型” (scalar type,例如 CGFloat 或 NSlnteger 等)的简单赋值操作。
d.assigin 可以用非 OC 对象,而 weak 必须用于 OC 对象
2.怎么用 copy 关键字?
这里有一个链接讲述的比较深入全面
iOS中关键字copy与mutableCopy的详解,看我你就都懂了
3.如何让自己的类用 copy 修饰符?如何重写带 copy 关键字的 setter?
继续链接了:
如何让自己的类用 copy 修饰符?如何重写带 copy 关键字的 setter?