定时器的实现和使用注意点

说起定时器应该都不陌生,具体的实现方式有3种:

1.NSTimer

2.CADisplayLink

3.GCD

1,2 使用时候都会存在循环引用 传递tareget 时候会有一个强引用,导致循环引用,最后dealloc 方法不调用 产生内存泄漏定时器一直在执行。

定时器的实现和使用注意点_第1张图片
image

解决办法

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张图片
image

方法 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/

你可能感兴趣的:(定时器的实现和使用注意点)