ARC下仅仅__strong是不能解决所有问题的,例如循环引用(应当废弃的对象在超出其生存周期后继续存在)
A对象持有B对象的强引用,B对象持有A对象的强引用,相互强引用,发生内存泄漏
上面通常以对象与其成员变量的形式发生,当然还有三者之间循环引用的场景等待
@interface Person : NSObject
@property(nonatomic, retain(MRC)/strong(ARC))Dog *dog;
@end
@interface Dog : NSObject
@property(nonatomic, retain(MRC)/strong(ARC))Person *owner;
@end
Person *p = [Person new];//p = 1
Dog *d = [Dog new];//d = 1
p.dog = d; // d = 2
d.owner = p; // p = 2
MRC:
[p release]; // p = 1
[d release]; // d = 1
ARC:
自动变量p与d出作用域后对对象的强引用失效后,两对象以循环引用的形式依然存在
MRC下使用assign,ARC下使用weak可以解决
@interface Person : NSObject
@property(nonatomic, retain(MRC)/strong(ARC))Dog *dog;
@end
@interface Dog : NSObject
@property(nonatomic, assign(MRC)/weak(ARC))Person *owner;
@end
Person *p = [Person new];//p = 1
Dog *d = [Dog new];//d = 1
p.dog = d; // d = 2
d.owner = p; // p = 1
MRC
[p release]; // p = 0 d= 1
[d release]; // d = 0
ARC
p,d出了作用域强引用失效,p引用的对象的废弃,Person对象成员变量_dog也被废弃,d引用的对象废弃
前面说过setter方法的实现,还是setter方法内的内存管理导致
MRC下assgin只是简单的赋值,因此不会导致循环引用
ARC下
{
Person __weak *owner;
}
- (void)setOwner:(Person __strong *)owner;
__weak修饰符只能用于iOS5以上的版本,在iOS4中可使用__unsafe_unretained修饰符来代替
__unsafe_unretained如其名unsafe,是不安全的所有权修饰符,尽管ARC 内存管理是编译器的工作,但附有__unsafe_unretained修饰符的变量不属于编译器的内存管理对象
id __unsafe_unretained obj = [[NSObject alloc] init];
__unsafe_unretained同__weak一样,不能强引用,对象生成就被释放。如果使用__weak,obj == nil,而使用__unsafe_unretained obj指向被废弃的内存,如果访问,会发生坏内存访问错误
assign类似类似__unsafe_unretained
__weak与__strong修饰符相反,提供弱引用,弱引用不能持有对象实例。类似MRC下的,p2 = p1;
id __weak obj = [[NSObject alloc] init];
编译器会给出警告,上述代码将自己生成并持有的对象赋值给__weak修饰的变量obj,生成的对象不存在强引用,生成立即被释放,编译器对此给出警告。如果像下面这样
id __strong obj0 = [[NSObject alloc] init];
id __weak obj1 = obj0;
将对象赋值给附有__strong修饰符的变量,之后再赋值给附有__weak修饰符的变量,就不会发生警告了。此时对象存在obj0的强引用,obj1的弱引用。生成不会立即释放