Farlanki

(Objective-C)@property后的关键字

字数统计: 687阅读时长: 2 min
2015/10/10 Share

setter相关修饰符

copy

copy关键字常用于NSStringNSArrayNSDictionary.这些类有两个特点:

  • 不可变(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
//implementation
...
-(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
//.h
@property (nonatomic,copy) NSString* name;
//.m
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
//.h
@property (nonatomic,copy) NSString* name;
//.m
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只提供属性gettersetter的原子性,并不保证对属性的所有操作都是线程安全的.
假设现在有一个名字为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的原子性,而不保证对属性的所有操作都是线程安全的.

CATALOG
  1. 1. setter相关修饰符
    1. 1.1. copy
    2. 1.2. 编译器优化
  2. 2. atomic