iOS 內(nèi)存管理 部分三

主要講解日常開發(fā)中定時(shí)器的選擇;

iOS 內(nèi)存管理 部分一
iOS 內(nèi)存管理 部分二
iOS 內(nèi)存管理 部分三
iOS 內(nèi)存管理 部分四


1. 日常開發(fā)中定時(shí)器的選擇

首先有個問題是NSTimer是否準(zhǔn)確? 答案是不準(zhǔn)確, 因?yàn)?code>NSTimer不論是在主線程還是子線程都是依賴于Runloop的, 就跟主線程刷新UI一樣, 我們寫完UI的刷新代碼并不會立即執(zhí)行, 而是等當(dāng)前Runloop周期結(jié)束時(shí)才會刷新, 所以NSTimer也是這樣, 如果某個Runloop周期處理的事情較多而耗時(shí)過長則直接導(dǎo)致NSTimer的時(shí)間變得不準(zhǔn)確;
替代方案:使用內(nèi)核級別的GCDtimer

- (void)GCDTimerAction {
    ///創(chuàng)建一個隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
    ///創(chuàng)建一個GCDTimer, 它的類型是DISPATCH_SOURCE, 注意Timer一定要強(qiáng)引用
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    /*
     設(shè)置Timer的一些參數(shù)
     參數(shù)1: 設(shè)置多久后觸發(fā)timer
     參數(shù)2: 設(shè)置間隔多久觸發(fā)一次timer
     */
    dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
    ///timer的調(diào)用方法
    dispatch_source_set_event_handler(self.timer, ^{
        NSLog(@"觸發(fā)GCDTimer");
    });
    ///重置timer
    dispatch_resume(self.timer);
}

下面我們對GCDTimer進(jìn)行下封裝, 使其更方便使用;

#封裝定時(shí)器的.h 文件
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface XTimer : NSObject
/// 創(chuàng)建一個定時(shí)器并啟動 返回這個定時(shí)器的 key
/// @param task 需要執(zhí)行的任務(wù)
/// @param begin 開始時(shí)間
/// @param interval 執(zhí)行間隔
/// @param repeat 是否重復(fù)
/// @param async 是否異步執(zhí)行
+ (NSString *)excuteTimerWithTask:(void(^)(void))task
                          begin:(double)begin
                       interval:(double)interval
                         repeat:(BOOL)repeat
                          async:(BOOL)async;
/// 取消hash值為hashStr的timer任務(wù)
+ (void)cancelTask:(NSString *)hashStr ;
@end
NS_ASSUME_NONNULL_END

#封裝定時(shí)器的.m 文件

#import "XTimer.h"
#import <os/lock.h>
static NSMutableDictionary *timerDic;
static os_unfair_lock lock;
static NSInteger   timerCount;

@implementation XTimer

+ (void)initialize {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        timerDic = [NSMutableDictionary dictionaryWithCapacity:0];
        lock = OS_UNFAIR_LOCK_INIT;
        timerCount = 0;
    });
}

/// 創(chuàng)建一個定時(shí)器并啟動 返回這個定時(shí)器的 key
/// @param task 需要執(zhí)行的任務(wù)
/// @param begin 開始時(shí)間
/// @param interval 執(zhí)行間隔
/// @param repeat 是否重復(fù)
/// @param async 是否異步執(zhí)行
+ (NSString *)excuteTimerWithTask:(void(^)(void))task
                          begin:(double)begin
                       interval:(double)interval
                         repeat:(BOOL)repeat
                          async:(BOOL)async {
    ///一些判斷條件
    if (!task || begin < 0 || (interval <= 0 && repeat)) {
        return nil;
    }
    dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0 ) : dispatch_get_main_queue();
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    os_unfair_lock_lock(&lock);
    [timerDic setValue:timer forKey:Str(timerCount)];
    timerCount ++;
    os_unfair_lock_unlock(&lock);
    NSLog(@"%@", timerDic.description);
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, begin * NSEC_PER_SEC, interval * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        task();
        if (!repeat) {
            [self cancelTask:Str(timerCount)];
        }
    });
    dispatch_resume(timer);
    return Str(timerCount);
}
/// 根據(jù) key 取消任務(wù)
+ (void)cancelTask:(NSString *)hashStr {
    if (!hashStr) {
        return;
    }
    os_unfair_lock_lock(&lock);
    dispatch_source_t source = timerDic[hashStr];
    if (!source) {
        return;
    }
    dispatch_source_cancel(source);
    [timerDic removeObjectForKey:hashStr];
    timerCount --;
    os_unfair_lock_unlock(&lock); 
}
///設(shè)定一個 key
NSString* Str(NSInteger count) {
    return [NSString stringWithFormat:@"%ld", count];
}
@end


參考文章和下載鏈接
文中測試代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子稠鼻,更是在濱河造成了極大的恐慌纬凤,老刑警劉巖避矢,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畜疾,死亡現(xiàn)場離奇詭異寸痢,居然都是意外死亡呀洲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進(jìn)店門啼止,熙熙樓的掌柜王于貴愁眉苦臉地迎上來两嘴,“玉大人,你說我怎么就攤上這事族壳°颈瑁” “怎么了?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵仿荆,是天一觀的道長贰您。 經(jīng)常有香客問我,道長拢操,這世上最難降的妖魔是什么锦亦? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮令境,結(jié)果婚禮上杠园,老公的妹妹穿的比我還像新娘。我一直安慰自己舔庶,他們只是感情好抛蚁,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惕橙,像睡著了一般瞧甩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上弥鹦,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天肚逸,我揣著相機(jī)與錄音,去河邊找鬼彬坏。 笑死朦促,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的栓始。 我是一名探鬼主播务冕,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼混滔!你這毒婦竟也來了洒疚?” 一聲冷哼從身側(cè)響起歹颓,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎油湖,沒想到半個月后巍扛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乏德,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年撤奸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喊括。...
    茶點(diǎn)故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡胧瓜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出郑什,到底是詐尸還是另有隱情府喳,我是刑警寧澤,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布蘑拯,位于F島的核電站钝满,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏申窘。R本人自食惡果不足惜弯蚜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剃法。 院中可真熱鬧碎捺,春花似錦、人聲如沸贷洲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恩脂。三九已至帽氓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間俩块,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工浓领, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玉凯,地道東北人。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓联贩,卻偏偏與公主長得像漫仆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泪幌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評論 2 359

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