说起定时器应该都不陌生,具体的实现方式有3种:
1.NSTimer
2.CADisplayLink
3.GCD
1,2 使用时候都会存在循环引用 传递tareget 时候会有一个强引用,导致循环引用,最后dealloc 方法不调用 产生内存泄漏定时器一直在执行。
解决办法
1.打破循环引用常用的方法 就是使用weak 对于block API 是管用的,
NSTimer scheduledTimerWithTimeInterval:<#(NSTimeInterval)#> repeats:<#(BOOL)#> block:<#^(NSTimer * _Nonnull timer)block#>
但是对于下面的API是无用的,内部依然会有强引用。
NSTimer scheduledTimerWithTimeInterval:<#(NSTimeInterval)#> target:<#(nonnull id)#> selector:<#(nonnull SEL)#> userInfo:<#(nullable id)#> repeats:<#(BOOL)#>
方法 2 消息转发,利用中间对象,实现弱引用。
@interface MFProxy :NSProxy
+ (instancetype)proxyWithTarget:(id)target;
@property (weak, nonatomic) id target;
@end
@implementation MFProxy
+ (instancetype)proxyWithTarget:(id)target
{
*// NSProxy对象不需要调用init,因为它本来就没有init方法*
MFProxy*proxy = [MFProxy alloc]; //有没有感觉很奇怪
proxy.target= target;
return proxy;
}
- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel
{
return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation*)invocation
{
[invocationinvokeWithTarget:self.target];
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[MFProxy proxyWithTarget:self] selector:@selector(timerTest) userInfo:nil repeats:YES];
}
解释 MFProxy*proxy = [MFProxy alloc]; //有没有感觉很奇怪 下面是这个类的声明 没有init 方法。
@interface NSProxy {
Class isa;
}
+ (id)alloc;
+ (id)allocWithZone:(nullable NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+ (Class)class;
- (void)forwardInvocation:(NSInvocation*)invocation;
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available");
- (void)dealloc;
- (void)finalize;
@property (readonly, copy) NSString *description;
@property(readonly,copy)NSString*debugDescription;
+ (BOOL)respondsToSelector:(SEL)aSelector;
- (BOOL)allowsWeakReferenceNS_UNAVAILABLE;
- (BOOL)retainWeakReferenceNS_UNAVAILABLE;
*// - (id)forwardingTargetForSelector:(SEL)aSelector;*
@end
不明白的戳这里http://ios.jobbole.com/87856/