看面试题的经常看到一些关于关键字的问题,在oc中修饰一个属性一般有4种关键词
原子性--- atomic/nonatomic。(默认atomic) atomic在setter/getter方法里加了锁,多线程情况下,一个线程进行setter操作,另外一个线程就需要等待上一个线程setter操作完毕才能操作。避免多线程下同时对一个属性进行setter或者getter操作造成数据混乱。但是可以一个线程进行setter另外一个线程进行getter操作,还是会造成数据混乱,并不能真正的保证线程安全,比如下面的代码
@property (atomic, assign) int leftTicketCount;
self.leftTicketCount = 50;
self.thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread1.name = @"1号窗口";
self.thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread2.name = @"2号窗口";
self.thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread3.name = @"3号窗口";
[self.thread1 start];
[self.thread2 start];
[self.thread3 start];
- (void)saleTicket
{
while (1) {
NSUInteger count = self.leftTicketCount;
if (count > 0) {
self.leftTicketCount = count - 1;
NSLog(@"%@卖了一张票, 剩余%zd张票", [NSThread currentThread].name, self.leftTicketCount);
} else {
return; // 退出循环
}
}
}
2017-06-21 12:38:45.727 [14137:733573] 1号窗口卖了一张票, 剩余32张票
2017-06-21 12:38:45.727 [14137:733574] 2号窗口卖了一张票, 剩余31张票
2017-06-21 12:38:45.832 [14137:733573] 1号窗口卖了一张票, 剩余29张票
2017-06-21 12:38:45.832 [14137:733575] 3号窗口卖了一张票, 剩余30张票
atomic并不能保证线程安全,只是保证了setter/getter的操作安全(同一时间多条线程不能同时操作setter或者getter)。想要安全还得加锁。
- (void)saleTicket
{
while (1) {
@synchronized(self) { // 开始加锁
NSUInteger count = self.leftTicketCount;
if (count > 0) {
self.leftTicketCount = count - 1;
NSLog(@"%@卖了一张票, 剩余%zd张票", [NSThread currentThread].name, self.leftTicketCount);
} else {
return; // 退出循环
}
} // 解锁
}
}
读/写权限(默认readwrite)---readwrite(读写)、readonly (只读)
但是readonly真的就不能被外界修改了吗? 没有什么是KVC不能修改的
内存管理语义---assign、strong、 weak、unsafe_unretained、copy
assign:适用于非OC对象,比较说一些基本数据类型
strong:适用于OC对象,需要对属性进行强引用
weak:适用于OC对象,弱引用,强调“非拥有”的关系,比如delegate属性
copy:copy修饰的属性的值是不可变的,相当于值引用,strong相当于地址引用。
用copy修饰一个属性
@property (nonatomic , copy) NSArray *array;
//执行下面代码
NSArray *tempArr = @[ @1, @2, @3, @4 ];
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:tempArr];
self.array = mutableArray;
[mutableArray removeAllObjects];;
NSLog(@"%@,%@",self.array,mutableArray);
输出
2017-06-21 13:54:58.765 循环引用[14684:849540] (
1,
2,
3,
4
),(
)
将array的copy修饰词改成strong,打印结果如下
2017-06-21 13:54:58.765 循环引用[14684:849540] (
),(
)
strong会引用mutableArray的地址给array,mutableArray释
放了,array也就释放了,但是copy是拷贝的值。
copy修饰的可变类型的属性,底层都会变成不可变类型
@property (nonatomic , copy) NSMutableArray *mutableArray;
执行下面代码:
self.mutableArray = [NSMutableArray arrayWithObjects:@3,@2,nil];
[self.mutableArray removeObjectAtIndex:0];
直接报错
erminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI removeObjectAtIndex:]: unrecognized selector sent to instance 0x60000023e180'
__NSArrayI表示self.mutableArray是不可变数组。
方法名---getter=<name> 、setter=<name> 起别名