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

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

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


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

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

- (void)GCDTimerAction {
    ///創(chuàng)建一個(gè)隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
    ///創(chuàng)建一個(gè)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);
}

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

#封裝定時(shí)器的.h 文件
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface XTimer : NSObject
/// 創(chuàng)建一個(gè)定時(shí)器并啟動(dòng) 返回這個(gè)定時(shí)器的 key
/// @param task 需要執(zhí)行的任務(wù)
/// @param begin 開(kāi)始時(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)建一個(gè)定時(shí)器并啟動(dòng) 返回這個(gè)定時(shí)器的 key
/// @param task 需要執(zhí)行的任務(wù)
/// @param begin 開(kāi)始時(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è)定一個(gè) key
NSString* Str(NSInteger count) {
    return [NSString stringWithFormat:@"%ld", count];
}
@end


參考文章和下載鏈接
文中測(cè)試代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容