簡(jiǎn)化NSTimer的使用

NSTimer的使用很方便也很簡(jiǎn)單,但使用時(shí)需要把創(chuàng)建的timer定義成一個(gè)成語(yǔ)變量或?qū)傩猿钟斜蓿蝗徽{(diào)用的block會(huì)一直執(zhí)行是晨,及時(shí)當(dāng)前對(duì)象已經(jīng)銷毀了,block還會(huì)執(zhí)行

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 80, 40, 20)];
    lbl.textColor = [UIColor blackColor];
    lbl.font = [UIFont systemFontOfSize:14];
    lbl.backgroundColor = [UIColor redColor];
    lbl.text = @"0---";
    lbl.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:lbl];
    
    __weak typeof(self) weakSelf = self;
    [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"weakself %@ %@",weakSelf,lbl.text);
    }];
//    [ZQQTimer timerWithHolder:self delay:0 TimeInterval:0 block:^(ZQQTimer *timer, NSInteger repeatCount) {
//        NSLog(@"aaa %ld %@",repeatCount,timer);
//        if (repeatCount == 5) {
//            [timer invalidate];
//        }
//    }];
//
//    
//    [self startTimerDelay:0 timeInterval:1 block:^(ZQQTimer *timer, NSInteger repeatCount) {
//        NSLog(@"%ld timer:%@",repeatCount,timer);
//        lbl.text = [NSString stringWithFormat:@"%ld",repeatCount];
//    }];
//    
//    [self startTimerWithBlock:^(ZQQTimer * timer, NSInteger repeatCount) {
//        
//    }];
}
- (void)dealloc
{
    NSLog(@"delloc %s",__FUNCTION__);
}

<pre>
2017-05-22 15:37:42.762 YZDisplayViewControllerDemo[31145:3580555] weakself <TestZQQTimerViewController: 0x7fe4d8549b70> 0---
2017-05-22 15:37:43.763 YZDisplayViewControllerDemo[31145:3580555] weakself <TestZQQTimerViewController: 0x7fe4d8549b70> 0---
2017-05-22 15:37:44.313 YZDisplayViewControllerDemo[31145:3580555] delloc -[TestZQQTimerViewController dealloc]
2017-05-22 15:37:44.763 YZDisplayViewControllerDemo[31145:3580555] weakself (null) 0---
2017-05-22 15:37:45.763 YZDisplayViewControllerDemo[31145:3580555] weakself (null) 0---
2017-05-22 15:37:46.763 YZDisplayViewControllerDemo[31145:3580555] weakself (null) 0---
2017-05-22 15:37:47.763 YZDisplayViewControllerDemo[31145:3580555] weakself (null) 0---
</pre>

現(xiàn)在特意封裝了一下NSTimer舔箭,讓在開(kāi)發(fā)或調(diào)試時(shí)隨意使用NSTimer而不用專門(mén)定義一個(gè)變量來(lái)持有timer罩缴,同時(shí)隨著使用timer的對(duì)象銷毀后,timer也自動(dòng)銷毀层扶,以提高開(kāi)發(fā)效率
基本原理如下:
1箫章、雖然表面使用者沒(méi)有專門(mén)定義一個(gè)變量來(lái)持有timer,但實(shí)際上通過(guò)runtime的方式來(lái)持有該timer
2镜会、由于使用runtime的objc_getAssociatedObject/objc_setAssociatedObject的方式持有一個(gè)間接變量檬寂,所以間接變量會(huì)隨著調(diào)用timer的這個(gè)宿主銷毀而銷毀,在銷毀時(shí)自動(dòng)同事銷毀timer
3戳表、添加一個(gè)使用timer時(shí)常用的計(jì)數(shù)器傳遞出來(lái)桶至,這樣方便timer的使用
4、自定義的ZQQTimer實(shí)現(xiàn)了invalidate方法匾旭,可以根據(jù)業(yè)務(wù)邏輯需要手動(dòng)代碼關(guān)閉timer
具體代碼如下
ZQQTimer.h

//
//  ZQQTimer.h
//  zqqkit
//
//  Created by liuhuan on 2017/5/22.
//  Copyright ? 2017年 zqq.love All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class ZQQTimer;
typedef void(^ZQQTimerBlock)(ZQQTimer * _Nonnull timer,NSInteger repeatCount);
@interface ZQQTimer : NSObject

+ (ZQQTimer *_Nonnull)timerWithHolder:(nonnull id)holder delay:(NSTimeInterval)delay TimeInterval:(NSTimeInterval)timeInterval block:(ZQQTimerBlock _Nullable )block;

- (void)invalidate;
@property (readonly, getter=isValid) BOOL valid;
@property (nonatomic,assign) NSInteger repeatCount;

@end

ZQQTimer.m

//
//  ZQQTimer.m
//  ZQQKit
//
//  Created by liuhuan on 2017/5/22.
//  Copyright ? 2017年 zqq.love. All rights reserved.
//

#import "ZQQTimer.h"
#import "NSObject+ZQQBindData.h"

#define kSaveZQQTimerInOneHolderKey @"kSaveZQQTimerInOneHolderKey"

@interface ZQQTimer()
@property (nonatomic,copy) ZQQTimerBlock block;
@property (nonatomic,strong) NSTimer * timer;
@property (nonatomic,weak) id holder;
@property (nonatomic,assign) NSTimeInterval timeInterval;
@property (nonatomic,assign) NSTimeInterval delay;
@end
@implementation ZQQTimer
+ (ZQQTimer *)timerWithHolder:(id)holder delay:(NSTimeInterval)delay TimeInterval:(NSTimeInterval)timeInterval block:(ZQQTimerBlock)block
{
   
    ZQQTimer *zqqTimer = [ZQQTimer new];
    NSMutableDictionary *dictM = [holder valueForKey:kSaveZQQTimerInOneHolderKey defaultValue:[NSMutableDictionary dictionary]];
    
    
    dictM[zqqTimer.description] = zqqTimer;
    zqqTimer.block = [block copy];
    zqqTimer.holder = holder;
    zqqTimer.timeInterval = timeInterval;
    zqqTimer.delay = delay;
    
    [zqqTimer showTimer];
    return zqqTimer;
}
- (void)showTimer
{
    
    if (self.timeInterval == 0) {
        self.timeInterval = 1;
    }
    __weak typeof(self) weakSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        weakSelf.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeInterval repeats:YES block:^(NSTimer * _Nonnull timer) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            strongSelf.repeatCount += 1;
            
            if (strongSelf.block) {
                strongSelf.block(strongSelf,strongSelf.repeatCount);
            }
            // -----防止數(shù)字越界 快捷鍵為gg
            if (strongSelf.repeatCount == NSIntegerMax) {
                strongSelf.repeatCount = 0;
            }
        }];
    });
   
}
- (void)invalidate
{
    [self.timer invalidate];
    self.timer = nil;
    NSMutableDictionary *dictM = self.holder[kSaveZQQTimerInOneHolderKey];
    [dictM removeObjectForKey:self.description];
    
}
- (BOOL)isValid
{
    return [self.timer isValid];
}
- (void)dealloc
{
    [self.timer invalidate];
    self.timer = nil;

    NSLog(@"dealloc %s",__FUNCTION__);
}
@end

測(cè)試代碼如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 80, 40, 20)];
    lbl.textColor = [UIColor blackColor];
    lbl.font = [UIFont systemFontOfSize:14];
    lbl.backgroundColor = [UIColor redColor];
    lbl.text = @"0---";
    lbl.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:lbl];
    
    __weak typeof(self) weakSelf = self;
    [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"weakself %@ %@",weakSelf,lbl.text);
    }];
    [ZQQTimer timerWithHolder:self delay:0 TimeInterval:0 block:^(ZQQTimer *timer, NSInteger repeatCount) {
        NSLog(@"aaa %ld %@",repeatCount,timer);
        if (repeatCount == 5) {
            [timer invalidate];
        }
    }];

    
    [self startTimerDelay:0 timeInterval:1 block:^(ZQQTimer *timer, NSInteger repeatCount) {
        NSLog(@"%ld timer:%@",repeatCount,timer);
        lbl.text = [NSString stringWithFormat:@"%ld",repeatCount];
        if (repeatCount == 5) { // 可以手動(dòng)取消timer的執(zhí)行
            [timer invalidate];
        }
    }];
    
    [self startTimerWithBlock:^(ZQQTimer * timer, NSInteger repeatCount) {
        
    }];
}
- (void)dealloc
{
    NSLog(@"delloc %s",__FUNCTION__);
}

這上面的代碼還用到了NSObject+ZQQBindData這個(gè)分類镣屹,這個(gè)之前博客里介紹過(guò),主要利用下標(biāo)語(yǔ)法价涝,讓任何NSObject都用有字典一樣簡(jiǎn)便的讀取變量的的功能女蜈,減少很多定義變量的麻煩

完整demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市色瘩,隨后出現(xiàn)的幾起案子伪窖,更是在濱河造成了極大的恐慌,老刑警劉巖居兆,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件覆山,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡泥栖,警方通過(guò)查閱死者的電腦和手機(jī)簇宽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)聊倔,“玉大人晦毙,你說(shuō)我怎么就攤上這事“颐铮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵孤荣,是天一觀的道長(zhǎng)甸陌。 經(jīng)常有香客問(wèn)我须揣,道長(zhǎng),這世上最難降的妖魔是什么钱豁? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任耻卡,我火速辦了婚禮,結(jié)果婚禮上牲尺,老公的妹妹穿的比我還像新娘卵酪。我一直安慰自己,他們只是感情好谤碳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布溃卡。 她就那樣靜靜地躺著,像睡著了一般蜒简。 火紅的嫁衣襯著肌膚如雪瘸羡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天搓茬,我揣著相機(jī)與錄音犹赖,去河邊找鬼。 笑死卷仑,一個(gè)胖子當(dāng)著我的面吹牛峻村,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锡凝,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼雀哨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了私爷?” 一聲冷哼從身側(cè)響起雾棺,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衬浑,沒(méi)想到半個(gè)月后捌浩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡工秩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年尸饺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片助币。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浪听,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出眉菱,到底是詐尸還是另有隱情迹栓,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布俭缓,位于F島的核電站克伊,受9級(jí)特大地震影響酥郭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜愿吹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一不从、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧犁跪,春花似錦椿息、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至惫叛,卻和暖如春倡勇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘉涌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工妻熊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仑最。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓扔役,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親警医。 傳聞我的和親對(duì)象是個(gè)殘疾皇子亿胸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容