文章目录
- 自动合成存取
- @property
- @synthesize
- @dynamic
- 一.读写性控制
- 二.setter相关修饰符
- 三.原子性修饰符
属性分为三大类:
- 读写性控制
- setter相关修饰符
- 原子性修饰符
自动合成存取
@property
@property
其实是在编译阶段由编译器自动帮我们生成setter方法,getter方法的
@synthesize
- 当我们在实现文件中不写
@synthesize propertyName
时,在Xcode 4.5之前的版本不会帮我们自动实现setter和getter方法,系统当然也不再会为我们生成对应的成员变量。但是在Xcode 4.5之后可以不用写@synthesize
了 - 当我们既定义了
@synthesize
,又在实现文件中人为重写setter和getter方法时,那么@synthesize
将不再工作,也就不会为我们创建没有定义的_propertyName
成员变量了,这时候如果在setter和getter方法中调用_propertyName
将会发生编译错误
@dynamic
@dynamic
告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。
一.读写性控制
readOnly
只读,只会生成getter方法,不会生成setter方法(但外部还是可以用KVC去赋值)readWrite
可读可写,会生成setter方法,也会生成getter方法(默认设置)
二.setter相关修饰符
assign
:表示直接赋值,用于基本数据类型,包括id类型,这个修饰符不会牵涉到内存管理,但是如果是对象类型,使用此修饰符则可能会导致内存泄露。(不会使引用计数+1,也就是直接赋值)retain
:针对对象类型进行内存管理,如果对基本数据类型使用,则X-code会直接报错,当给对象类型使用此修饰符时,setter方法会先将旧的对象属性release
掉,在对新的对象进行一次赋值并进行一次retain
操作 (会使引用计数+1)week
:打开ARC时才会使用,相当于assign
,可以把对应的指针变量置为nil
strong
:打开ARC时才会使用,相当于retain
copy
:建立一个索引计数为1的对象,在赋值时使用传入值的一份拷贝
copy
NSString
、NSArray
、 NSDictionary
等等经常使用copy
关键字,是因为他们有对应的可变类型:NSMutableString
、NSMutableArray
、 NSMutableDictionary
.为确保对象中的属性值不会无意间变动,应该在设置新属性值时拷贝一份保护其封装性block,也经常使用copy,关键字block。
用@property
声明的NSString
(或NSArray
,NSDictionary
)经常使用copy
关键字,为什么?如果改用strong关键字,可能造成什么问题?
- 因为父类指针可以指向子类对象,使用
copy
的目的是为了让本对象的属性不受外界影响,使用copy
无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.如果我们使用是strong
,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.
深浅拷贝
关键字 | 注释 |
---|
浅复制(shallow copy) | 在浅复制操作时,对于被复制对象的每一层都是指针复制。 |
深复制(one-level-deep copy) | 在深复制操作时,对于被复制对象,至少有一层是深复制。 |
完全复制(real-deep copy) | 在完全复制操作时,对于被复制对象的每一层都是对象复制。 |
非集合类对象的 copy 与 mutableCopy
[不可变对象 copy]
[不可变对象 mutableCopy]
[可变对象 copy]
[可变对象 mutableCopy]
例如:
NSArray* arr1 = [NSArray arrayWithObjects:@"苹果", @"桃子", @"葡萄", nil];NSArray* arr3 = [arr1 mutableCopy];NSLog(@"arr1 = %p, arr2 = %p, arr3 = %p", arr1, arr2, arr3);
- 如上,arr1和arr2地址相同,但与arr3不相同。
- 因为arr1是不可变对象,arr2复制时使用
copy
关键字,进行了浅拷贝 - arr3复制时使用
mutableCopy
关键字,创建了一个新的对象,进行了深拷贝
copy与strong关键字的差异
当我分别使用copy和strong关键字定义属性再进行复制时
@property (nonatomic, copy) NSArray* arr1;
@property (nonatomic, strong) NSArray* strongArr1;
NSMutableArray* test = [NSMutableArray arrayWithObjects:@"a", @"b", @"c", nil];self.arr1 = test;self.strongArr1 = test;NSLog(@"%p , %p",test, _arr1);NSLog(@"%p , %p",test, _strongArr1);
- 可以看到,当我对test数组分别对copy和strong关键字定义的数组进行赋值时,用copy关键字声明的arr1属性的地址发生了变化,也就是产生了一个新的对象,进行了深复制。而用strong关键字声明的strongArr1属性的地址和test相同,进行了浅复制
- strong修饰下,我们的strongArr1会持有原来的对象,使原来的对象引用计数+1,属于浅拷贝,这时候进行操作时,test和strongArr1的值都会发生改变
- 一般来说对于不可变对象我们使用copy修饰从而防止它的值发送改变,而可变的对象使用strong修饰。
三.原子性修饰符
atomic
:表示是线程安全的
nonatomic
:表示是非线程安全的,使用此属性性能会提高一些
(系统默认是atomic)