你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> ios多線程操作— GCD延遲操作與一次性代碼

ios多線程操作— GCD延遲操作與一次性代碼

編輯:IOS開發綜合
使用GCD函數可以進行延時操作,該函數為
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    });


現在我們來分解一下參數 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)) : NSEC_PER_SEC在頭文件中的定義如下:
#define NSEC_PER_SEC 1000000000ull /* nanoseconds per second */ 該參數表示從現在開始經過多少納秒 dispatch_get_main_queue():表示主隊列 ^{ }:表示一個block任務。 我們可以來測試一下經過多少納秒之後,由主隊列調度任務是異步執行還是同步執行,代碼如下:
 //  when 時間 從現在開始經過多少納秒
    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
   
    void (^task)() = ^ {
        // 延遲操作執行的代碼
        NSLog(@"%@", [NSThread currentThread]);
    }; 
    // 經過多少納秒,由主隊列調度任務異步執行
    dispatch_after(when, dispatch_get_main_queue(), task);
    // 先執行就是異步,後執行就是同步
    NSLog(@"come here");

執行結果如下: \
由此可見主隊列中調度任務是異步執行的 再將執行隊列改為全局隊列和串行隊列,得到的結果完全是一樣的,由此可知該函數執行的是異步操作。
GCD中有個函數能夠保證某段代碼在程序運行過程中只被執行1次!該函數如下:
static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
       
    })

dispatch_once_t在頭文件中得定義如下:
typedef long dispatch_once_t; 由此可知該類型是個long類型。當onceToken等於0時就會執行block代碼。dispatch_once是線程安全的,只要涉及到線程安全就會涉及到鎖,dispatch_once內部也有一把鎖,性能比互斥鎖高! 利用該函數我們可以來寫一個單例模式 單例模式可以保證在程序運行過程,一個類只有一個實例且該實例易於供外界訪問,從而方便控制實例個數,並節約系統資源,當應用程序需要共享一份資源時就可以用單例模式來實現。單例模式分ARC與MRC兩種情況,我們可以用宏判斷是否為ARC環境

 

#if __has_feature(objc_arc)
// ARC
#else
// MRC
#endif

 

ARC環境下簡單地單例模式:
@implementation SoundTools
// 定義一個靜態成員,保存唯一的實例
static id instance;

// 保證對象只被分配一次內存空間,通過dispatch_once能夠保證單例的分配和初始化是線程安全的
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

// 保證對象只被初始化一次
+ (instancetype)sharedSoundTools {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (id)copyWithZone:(NSZone *)zone {
    return instance;
}
@end

測試代碼如下:
- (void)viewDidLoad {
    [super viewDidLoad];
    
    SoundTools *s1 = [SoundTools sharedSoundTools];
    NSLog(@"%p", s1);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    SoundTools *s2 = [SoundTools sharedSoundTools];
    
    NSLog(@"%p", s2);
}


兩個方法打印出來的地址完全一樣!
在MRC環境下有如下代碼:
// 定義一個靜態成員,保存唯一的實例
static id instance;

// 保證對象只被分配一次內存空間,通過dispatch_once能夠保證單例的分配和初始化是線程安全的
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

// 保證對象只被初始化一次
+ (instancetype)sharedSoundTools {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (id)copyWithZone:(NSZone *)zone {
    return instance;
}

#pragma mark - MRC內存管理方法
/**
 因為單例的對象是保存在靜態區的,因此需要重寫 內存管理方法,取消默認的引用計數操作!
 */
// 默認會將引用計數-1
- (oneway void)release {
    // 什麼也不做,跟highlight類似
}

// 默認引用計數+1,同時返回一個對象
- (instancetype)retain {
    return instance;
}

// 默認添加自動釋放標記,延遲釋放!
- (instancetype)autorelease {
    return instance;
}

// 返回有多少個對象對當前對象引用的數值
- (NSUInteger)retainCount {
    // 出處:limits.h 會根據CPU的架構自行調整整數的長度
    return ULONG_MAX;
}


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved