代碼如下 可以看到timer與控制器之間有相互強引用的關(guān)系 dealloc不會執(zhí)行
原因無非是 當(dāng)前控制器 對 timer有一個強引用 而定時器內(nèi)部的target對 當(dāng)前的控制器 也存在一個強引用
- (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];
}];
方案二
既然產(chǎn)生的原因是NSTimer內(nèi)部的target對當(dāng)前控制器存在強引用 那么可以創(chuàng)建一個OtherObject讓NSTimer內(nèi)部的target的強引用 指向該OtherObject 而OtherObject內(nèi)部的target弱引用指向當(dāng)前控制器
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