代码如下 可以看到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弱引用指向当前控制器
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[Proxy proxyWithTarget:self] selector:@selector(test) userInfo:nil repeats:YES];
#import <Foundation/Foundation.h>
@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 <NSObject> {
Class isa;
}
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[LDProxy proxyWithTarget:self] selector:@selector(test) userInfo:nil repeats:YES];
#import <Foundation/Foundation.h>
@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