循环引用

1、循环引用对App的影响

内存无法释放 >> 性能降低 >> 闪退

2、循环引用具体存在情景(相互包含、block、delegate、NSTimer)

----(假如有ZQViewControllerZQObject对象)

  • 相互包含
//ZQViewController.m中是如下Code
@interface ZQViewController ()
@property (nonatomic,strong) ZQObject *                 object;
@end

@implementation ZQViewController
- (void)dealloc {
    NSLog(@"循环引用该方法不会执行");
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.object = [[ZQObject alloc] init];
    _object.viewController = self;
}
//ZQObject.h中是如下Code
#import 
@interface ZQObject : NSObject
@property (nonatomic,strong) UIViewController  *      viewController;
@end

在如上Code情况中:
ZQViewController强引用了ZQObject;同时ZQObject强引用了ZQViewController;这个时候由于二者的RetainCount不可能为0,所以导致对象无法释放。
注:CFGetRetainCount((__bridge CFTypeRef)(_object))

  • block
#import "ZQViewController.h"

#import "ZQObject.h"
@interface ZQViewController ()
@property (nonatomic,strong) ZQObject *                 object;
@end

@implementation ZQViewController
- (void)dealloc {
    NSLog(@"循环引用该方法不会执行");
}
- (void)viewDidLoad {
    [super viewDidLoad];
    //情况一:
    self.object = [[ZQObject alloc] init];
    self.object.testBlock = ^{
        [self doSomething];
    };
    //情况二:
    self.object = [[ZQObject alloc] init];
    __weak typeof(self) weakSelf = self;
    self.object.testBlock = ^{
        __strong typeof (weakSelf) strongSelf = weakSelf;
        [strongSelf doSomething];
    };
}
- (void)doSomething {
    NSLog(@"做一些事情");
}
#import 

typedef void (^testBlock)(void);
@interface ZQObject : NSObject
@property (nonatomic, copy) testBlock                 testBlock;
@end

在如上Code情况中:
block在copy时都会对block内部用到的对象(self)进行强引用的。
ZQObject中的block的方法体里面又使用了ZQViewController,此时就出现了相互强引用,这个时候由于二者的RetainCount不可能为0,所以导致对象无法释放。

  • delegate
#import "ZQViewController.h"
#import "ZQObject.h"

@interface ZQViewController ()


@property (nonatomic,strong) ZQObject *                 object;
@end

@implementation ZQViewController

- (void)dealloc {
    NSLog(@"循环引用该方法不会执行");
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.object = [[ZQObject alloc] init];
    _object.delegate = self;
}
#import 

@protocol ObjectDelegate 

@end

@interface ZQObject : NSObject
@property (nonatomic, weak) id  delegate;
@end

ZQViewController持有ZQObject对象,同时_object.delegate = self;ZQObject 持有ZQViewController```对象,delegate如果也是strong类型引用,二者的RetainCount不可能为0,所以导致对象无法释放。

  • NSTimer
    NSTimer 因为是比较特殊的情况,所以很容易被我们忽略。
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti
                                     target:(id)aTarget
                                   selector:(SEL)aSelector
                                   userInfo:(nullable id)userInfo
                                    repeats:(BOOL)yesOrNo;

方法的最后一个参数(repeats)为YES时,NSTimer会保留目标(target)对象,等到自身失效才释放。执行完任务后,一次性的定时器会自动失效;重复性的定时器,需要主动调用invalidate方法才会失效。
创建定时器时,当前控制器引用而定时器了,在给定时器添加任务时,定时器保留了self(当前控制器对象).这里就出现了循环引用。

你可能感兴趣的:(循环引用)