NStimer的循环引用探究

代码如下 可以看到timer与控制器之间有相互强引用的关系 dealloc不会执行
原因无非是 当前控制器 对 timer有一个强引用 而定时器内部的target对 当前的控制器 也存在一个强引用

- (void)viewDidLoad {
    [super viewDidLoad];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(test) userInfo:nil repeats:YES];
}
- (void)dealloc
{
    [self.timer invalidate];
}
- (void)test
{
    NSLog(@"99 ***** 999");
}

解决方案如下

方案一
 __weak typeof(self)weakSelf = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        [weakSelf test];
    }];
方案二

既然产生的原因是NSTimer内部的target对当前控制器存在强引用 那么可以创建一个OtherObject让NSTimer内部的target的强引用 指向该OtherObject 而OtherObject内部的target弱引用指向当前控制器

853D59ACFEC816C98ECDB3EE65DB9E59.png
A912912CF5B604C6A9C32E8BBD6D6289.png
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[Proxy proxyWithTarget:self] selector:@selector(test) userInfo:nil repeats:YES];
#import 
@interface Proxy : NSObject
+ (instancetype)proxyWithTarget:(id)target;
@property(nonatomic,weak)id target;
@end
#import "Proxy.h"
@implementation Proxy
+ (instancetype)proxyWithTarget:(id)target
{
    Proxy * p = [[Proxy alloc]init];
    p.target = target;
    return p;
}
-(id)forwardingTargetForSelector:(SEL)aSelector
{
    return self.target;
}
@end

NSProxy方式

@interface NSProxy  {
    Class   isa;
}
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[LDProxy proxyWithTarget:self] selector:@selector(test) userInfo:nil repeats:YES];

#import 
@interface LDProxy : NSProxy
+ (instancetype)proxyWithTarget:(id)target;
@property(nonatomic,weak)id target;
@end
#import "LDProxy.h"
@implementation LDProxy
+ (instancetype)proxyWithTarget:(id)target
{
    LDProxy * p = [LDProxy alloc];
    p.target = target;
    return p;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
    [invocation invokeWithTarget:self.target];
}
@end

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