readonly和readwrite
这2个简单,一个只读的,一个可读可写的。一般在使用readonly的地方,防止KVC修改值,都会加上+ (BOOL)accessInstanceVariablesDirectly,返回NO;
atomic和nonatomic
atomic原子的,系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。但是对其修饰的比如数组添加删除成员变量,是线程不安全的。
nonatomic是线程不安全的,nonatomic的速度要比atomic的快。
atomic与nonatomic的本质区别其实也就是在setter方法上的操作不同
nonatomic对象setter和getter方法的实现:
- (void)setCurrentImage:(UIImage *)currentImage
{
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];
}
}
- (UIImage *)currentImage
{
return _currentImage;
}
atomic对象setter和getter方法的实现:
- (void)setCurrentImage:(UIImage *)currentImage
{
@synchronized(self) {
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];
}
}
}
- (UIImage *)currentImage
{
@synchronized(self) {
return _currentImage;
}
}
assign
修饰基本数据类型,int、bool
修饰对象类型时,不改其变引用计数
会产生悬垂指针
weak
不改变被修饰对象的引用计数
所指向的对象在被释放之后会自动置为nil
__unsafe_unretained
修饰对象类型,不改其变引用计数
会产生悬垂指针
strong
修饰对象类型,产生抢引用,引用计数加1
copy深拷贝浅拷贝
浅拷贝:对内存地址的复制,目标对象和原对象指向同一个内存地址,引用计数加1
深拷贝:目标对象和原对象指向两个内容相同的内存空间,不影响引用计数

image.png
可变对象的copy和mutableCopy都是深拷贝
不可变对象的copy是浅拷贝,可变对象的copy是深拷贝
copy返回的都是不可变对象
MRC下如何重写retain变量的setter方法?
- (void)setObj:(id)obj
{
if (_obj != obj) {
[_obj release];
_obj = [obj retain];
}
}
_obj != obj 这个判断是防止这2个是同一个对象时,下面[_obj release]会把这个对象释放掉,外面再调用时会崩溃。