相信做iOS开发的童靴对NSTimer应该不会陌生,使用它遇到的坑还真不少。下面我就结合自己项目中遇到的问题,讨论一下NSTimer在使用的中我们要避开的那些坑:
坑1:创建的方式
Apple API为我们提供了一下几种创建NSTimer的方式:
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(nullable id)ui repeats:(BOOL)rep;
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:weakSelf selector:@selector(countDownHandler) userInfo:nil repeats:YES];
#import
typedef void(^SFWeakTimerBlock)(id userInfo);
@interface SFWeakTimer : NSObject
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
target:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)repeats;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(SFWeakTimerBlock)block
userInfo:(id)userInfo
repeats:(BOOL)repeats;
@end
#import "SFWeakTimer.h"
@interface SFWeakTimerTarget : NSObject
@property (weak, nonatomic) id target;
@property (assign, nonatomic) SEL selector;
@property (weak, nonatomic) NSTimer *timer;
- (void)fire:(NSTimer *)timer;
@end
@implementation SFWeakTimerTarget
- (void)fire:(NSTimer *)timer {
if (self.target && [self.target respondsToSelector:self.selector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self.target performSelector:self.selector withObject:timer.userInfo afterDelay:0.0f];
#pragma clang diagnostic pop
} else {
[self.timer invalidate];
}
}
@end
@implementation SFWeakTimer
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
target:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)repeats {
SFWeakTimerTarget *timerTarget = [[SFWeakTimerTarget alloc] init];
timerTarget.target = aTarget;
timerTarget.selector = aSelector;
timerTarget.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:timerTarget selector:@selector(fire:) userInfo:userInfo repeats:repeats];
return timerTarget.timer;
}
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(SFWeakTimerBlock)block
userInfo:(id)userInfo
repeats:(BOOL)repeats {
return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(sf_timerUsingBlockWithObjects:) userInfo:@[[block copy], userInfo] repeats:repeats];
}
+ (void)sf_timerUsingBlockWithObjects:(NSArray *)objects {
SFWeakTimerBlock block = [objects firstObject];
id userInfo = [objects lastObject];
if (block) {
block(userInfo);
}
}
@end
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];