平常我們常見的循環引用有block循環引用和對象之間相互強引用兩種情況;
1、block循環引用問題:例如
#import "Person.h"
typedef void(^PersonBlock)(NSString *name);
@interface Person()
@property (nonatomic,strong)NSArray *propertyS;
@property (nonatomic,strong)PersonBlock block;
@end
@implementation Person
- (id)init
{
if (self = [super init]) {
self.propertyS = @[@"女", @"23"];
self.block = ^(NSString *name){
NSLog(@"arr:%@", self.propertyS);
};
}
return self;
}
@end
其中在block中調用propertyS會有警告出現,這是因爲在block中調用了self所擁有的東西,引起了循環引用,那麼這個循環引用具體怎樣引起的呢?
(1)block中引用了self,self被block retain,propertyS又retain了該block的一個拷貝
(2)propertyS是在self中定義賦值的,因此是被self retain的
因此形成了循環引用,不會調用dealloc
解決方法是利用__weak或者__unsafe__unretained去修飾self(在ARC模式下),在MRC模式下用__block修飾
2、兩個對象之間相互強引用:
@interface Person : NSObject
{
Person *person1;
Person *person2;
NSArray *array;
}
@property (readwrite,assign)Person *person1;
@property (readonly)Person *person2;
@end
person擁有兩個Person對象,每個對象又都擁有一個NSArray對象。屬性person1和person2都指向了彼此的Person對象。那麼兩個對象間形成了強引用,ARC將不會銷燬這個對象。爲了阻止這種事的發生,聲明其中一個屬性爲弱引用即可(__weak Person *person2)。這樣,當person2指向空並且Person對象超出範圍時,ARC可以安全的給這個對象發送一個release消息。
__weak指示符既可以聲明弱引用,也可以聲明空引用。__unsafe_unretained聲明弱引用,不是空引用。如果要用後者,那麼要自己處理空引用,否則會內存泄漏