在iOS9或更老系统版本中使用NSTimer+Block方法

在iOS9或更老系统版本中使用NSTimer+Block方法

在许多倒计时功能(例如获取短信验证码)的时候,我们通常会用以下的方法,
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

这个方法需要设置target和selector,写起来非常不方便而且代码分散到各处,看起来就好丑。
也许苹果大大也觉得这样不好用,于是从iOS10.0开始,NSTimer新增了几个带block的方法,于是乎又感觉到了block的方便与强大。
例如与上述方法具有相同意义的
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

有了它,再写哪些什么button倒计时就简单多了,也更容易阅读,

- (void)startCountDownCode{
    __block NSInteger sec=60;
    self.codeButton.enabled=NO;
    weak_self_define;
    [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        sec=sec-1;
        [weakSelf.codeButton setTitle:[NSString stringWithFormat:@"%lds",(long)sec] forState:UIControlStateDisabled];
        if (sec<=0) {
            weakSelf.codeButton.enabled=YES;
            [timer invalidate];
        }
    }];
}

可是,这里有一个限制,需要iOS10.0及以上才有这个方法,其他系统版本直接崩溃。
那么iOS9和更低的版本就要用回那个老方法吗?那么难用,还丑。坚决不!
我们要想办法让这个方法兼容到iOS9!
得益于强大的Runtime和Category,可以直接给NSTimer加一个block属性,直接动手不墨迹。
我们给项目添加一个文件NSTimer+block.m,覆盖了原有的block方法,使得iOS9以下也可以用。
内容如下:

#import < objc/runtime.h >
@interface NSTimer (BLock)
@property (nonatomic,copy) void(^blockIOS9)(NSTimer* timer); 
//这个属性本身是不存在的,需要用runtime添加
@end

@implementation NSTimer (Block)

+(NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)interval 
repeats:(BOOL)repeats block:(void (^)(NSTimer *))block
{
    NSTimer* timer=[NSTimer scheduledTimerWithTimeInterval:interval 
target:self selector:@selector(timerCustomSeletor:) 
userInfo:nil repeats:repeats]; 
//这里的self是指NSTimer的类 ,于是selector也必须是类方法
    timer.blockIOS9=block;
    return timer;
}

+(void)timerCustomSeletor:(NSTimer*)timer
{
    __weak typeof(timer) wetimer=timer;  //这里应该可以不用weak修饰
//这里的参数timer是NSTimer的实例,也就是上述类方法返回的timer
    if(timer.blockIOS9) //执行block
    {
        timer.blockIOS9(wetimer);
    }
}

-(void)setBlockIOS9:(void (^)(NSTimer *))blockIOS9
{
    objc_setAssociatedObject(self, @selector(blockIOS9), blockIOS9, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

-(void (^)(NSTimer *))blockIOS9
{
    return objc_getAssociatedObject(self, @selector(blockIOS9));
}

@end

就这样,使得iOS10才能用的新方法也能在旧版本使用了。
唯一不足之处是,会看见大量的警告,

在iOS9或更老系统版本中使用NSTimer+Block方法_第1张图片
屏幕快照 2018-03-29 13.59.00.png


如果有同学知道消除这些警告的方法,请告诉我,谢谢!

你可能感兴趣的:(在iOS9或更老系统版本中使用NSTimer+Block方法)