setter相关修饰符
copy
copy关键字常用于NSString
、NSArray
、NSDictionary
.这些类有两个特点:
- 不可变(immutable)
- 遵守了
NSCopying
协议
如果在赋值的时候希望对象是被复制一份而不是指向同一个对象那么就需要添加copy
关键字
copy
关键字会影响setter
方法:
1 2 3 4 5 6 7
| - (void)setName:(NSString *)newName { if (name != newName) { [name release]; name = [newName copy]; // name’s retain count has been bumped up by 1 } }
|
如果在一个mutable
的属性加上copy关键字:
1 2 3 4 5 6 7 8 9 10
| //@interface ... @property(copy) NSMutableArray *myMutableArray; ... //implementation ... NSMutableArray *newMutableArray = [NSMutableArray arrayWithObjects:@"foo",@"bar", nil]; self.myMutableArraay = newMutableArray; [self.myMutableArray removeObjectAtIndex:0]; //提示unrecognized selector ...
|
因为copy
方法返回的是不可变对象,对于NSArray的子类,返回的自然是一个NSArray对象,自然没有removeObjectAtIndex:
方法.
我们可以实现可变对象的setter:
1 2 3 4 5 6 7 8 9 10 11
| ... -(void)setMyMutableArray:(NSMutableArray *)myMutableArray { _myMutableArray = [myMutableArray mutableCopy]; } ... NSMutableArray *newMutableArray = [NSMutableArray arrayWithObjects:@"foo",@"bar", nil]; self.myMutableArraay = newMutableArray; [self.myMutableArray removeObjectAtIndex:0]; ...
|
可以运行.
如果同时使用了copy
关键字和手动添加setter,那么使用的将是手动添加的setter.
编译器优化
1.当copy修饰的属性赋值时的对象是一个不可变对象的时候,不会发生内存的拷贝行为,发生的仅仅是指针的强引用。
2.当copy修饰的属性赋值的对象是一个可变对象的时候才会发生内存的拷贝。
1 2 3 4 5 6 7
| @property (nonatomic,copy) NSString* name;
NSString* tempName = [NSString stringWithString:@"name"]; self.name = tempName; NSLog(@"tempname : %p" , tempName); NSLog(@"name : %p" , self.name);
|
1 2 3
| //输出 2016-07-21 18:44:35.845 TT[1294:575627] tempname : 0x1005dd0b8 2016-07-21 18:44:35.845 TT[1294:575627] name : 0x1005dd0b8
|
mutable的情况:
1 2 3 4 5 6 7
| @property (nonatomic,copy) NSString* name;
NSMutableString* tempName = [NSMutableString stringWithString:@"name"]; self.name = tempName; NSLog(@"tempname : %p" , tempName); NSLog(@"name : %p" , self.name);
|
1 2 3
| //输出 2016-07-21 18:45:46.617 TT[1305:582317] tempname : 0x7fe32ac22a20 2016-07-21 18:45:46.618 TT[1305:582317] name : 0xa000000656d616e4
|
atomic
设置属性的时候,默认添加atomic
修饰词.atomic
只提供属性getter
、setter
的原子性,并不保证对属性的所有操作都是线程安全的.
假设现在有一个名字为name
的属性,并且是atomic的.假设从线程A调用[self setName:@"A"]
,从线程B调用[self setName:@"B"]
,从线程C调用[self Name]
,这三个线程同时尝试访问name属性,那么一次只有一个线程可以访问到name属性,而其他线程会被堵塞.如果属性是nonatomic
的,那么三个线程将同时访问name属性.
如果线程D在这时调用[name release]
,那么这个操作可能会导致崩溃,因为release操作不包含任何getter/setter的调用,atomic在这时自然没有起作用.
所以说,atomic
只提供getter/setter
的原子性,而不保证对属性的所有操作都是线程安全的.