iOS中的assign,retain,copy,weak,sto
iOS中的OC是一门面向对象的编辑语言,每一个对象都是类的实例,在OC中每一个对象都有一个名为isa的指针,指向该对象的类。所有NSObject是一个包含isa指针的结构体。
1.强弱引用的区别
(1) assign 和 weak 一样是一个弱引用;
(2) strong是强引用;
区别:他们最重要的区别是引起内存的变化和内存管理,在setter方法赋值过程中,指针的数值会发生变化。如:
(1)- property(nonatomic, assign)NSObject * a;
- (void)setA:(int) a {
- a = a;
}
在弱引用的情况下,直接进行赋值,即原本指针的值为1,赋值以后没有将指针的数字增大,还是1;
(2)- property(nonatomic, strong)NSObject * a;
- (void)setA:(int) a {
[_a release];
- a = [a strong];
}
在强引用的情况下,进行+1之后再赋值,使用过后-1仍然是1,返回之前的状态,置为nil。
而assign,在使用之后也不进行-1,还是1,但是指向的东西却没有了,总是没有变化,也不会指向nil,所以就会发生混乱。
assign和weak的区别
本质区别
速度比较: __unsafe_unretained > __weak
@property (nonatomic, assign) Person *person; // 真实类型是 Person *__unsafe_unretained _person;
__unsafe_unretained的特点:
1.不是强引用, 不能保住OC对象的命
2.如果引用的OC对象销毁了, 指针并不会被自动清空, 依然指向销毁的对象(很容易产生野指针错误: EXC_BAD_ACCESS)
@property (nonatomic, weak) Person *person; // Person * _Nullable __weak person;
__weak的特点:
1.不是强引用, 不能保住OC对象的命
2.如果引用的OC对象销毁了, 指针会被自动清空(变为nil), 不再指向销毁的对象(永远不会产生野指针错误).可以归纳为弱引用在对象释放后置为nil,避免了错误的内存访问,及weak可以在不增加对象的引用计数的同时,又使得指针的访问是安全的
- 用途
- assign一般用在基本数据类型上面, 比如int\double等
- weak一般用在代理对象上面, 或者用来解决循环强引用的问题
assign: 简单的直接赋值,相当于说两个对象指向同个内存区,一个地方的变了,其他的也跟着改变。
copy: 用于希望保持一份传入值的拷贝,而不是值自身的情况,即把原来的对象完整的赋值到另外一地方,重新加载一内存区,一个地方变了不影响另一个地方的对象。一般用来修饰NSString等有对应可变类型的对象,因为他们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改 ,应该在设置属性是拷贝一份。而若用strong修饰,如果对象在外部被修改了,会影响到属性。
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数 为1
Copy 其实是建立了一个相同的对象,而 retain 不是:
比如一个 NSString 对象,地址为 0×1234,内容为@”qe”
Copy 到另外一个 NSString 之 后,地址为 0×2222,内容相同,新的对象 retain 为 1, 之前的对象没有变化
retain 到另外一个 NSString 之 后,地址相同(建立一个指针,指针拷贝),内容当然相 同,这个对象的 retain 值+1
assign 地址还是0x1234,内容也还是“qe”。
block属性为什么需要用copy来修饰?
因为在MRC下,block在创建的时候,它的内存是分配在栈(stack)上的,而不是在堆(heap)上,可能被随时回收。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。通过copy可以把block拷贝(copy)到堆,保证block的声明域外使用。在ARC下写不写都行,编译器会自动对block进行copy操作。
注意:
ARC下的strong等同于MRC下的retain都会把对象引用计数加1
block属性需要用copy来修饰
同时,在ARC下,要避免block出现循环引用,经常会:__weak typedof(self) weakSelf = self;
copy : 只用于NSString\block
基于weak的特性,可以有[ weak singleton]的模式,即在所有使用该单例的对象释放之后,单例对象本身也会释放。 代码如下:
+ (id)sharedInstance
{
static __weak SingletonClass *instance;
SingletonClass *strongInstance = instance;
@synchronized(self) {
if (strongInstance == nil) {
strongInstance = [[[self class] alloc] init];
instance = strongInstance;
}
}
return strongInstance;
}
Controller A, B, C 都可以持有 SingletonClass 的强引用,一旦 A,B,C 都销毁后,SingletonClass 的单例对象也会随之销毁,sharedInstance中的weak就像是一个智能管家,在使用完sharedInstance之后就置为nil销毁,当sharedInstance再次被调用时,sharedInstance又会重新被创建。