貓貓學iOS(五十二)多線程網路之GCD下單例設計模式

來源:互聯網
上載者:User

標籤:共用   設計模式   網路   多線程   控制   

貓貓分享,必須精品

原創文章,歡迎轉載。轉載請註明:翟乃玉的部落格
地址:http://blog.csdn.net/u013357243?viewmode=contents

單例模式1:單例模式的作用

可以保證在程式運行過程,一個類只有一個執行個體,而且該執行個體易於供外界訪問
從而方便地控制了執行個體個數,並節約系統資源

單例模式的使用場合
在整個應用程式中,共用一份資源(這份資源只需要建立初始化1次)

簡單來說,就是我弄了一個工具類,他就有一份,比如我設計了一個音樂播放器NYPlayer,這個播放器類我就想他有一個,這就是單例,我用的時候我只需要讓播放器幹活,如果多個的話我不知道指定那個,或者有重複會出bug。
百度百科是這樣說的:單例模式是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例類的特殊類。通過單例模式可以保證系統中一個類只有一個執行個體而且該執行個體易於外界訪問,從而方便對執行個體個數的控制並節約系統資源。如果希望在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。
簡單來說,就是讓一個類的事物裡面只有一個對象。

2:ARC中,單例模式的實現

過程:
在.m中保留一個全域的static的執行個體
這裡要用static,記住他,稍後我回寫一個關於static關鍵詞的部落格。

static id _instance;

重寫allocWithZone:方法,在這裡建立唯一的執行個體(注意安全執行緒)
建立類的時候調用[類名 alloc]方法的時候,內部會自動調用allcWithZone方法,載入一個空間,所以我們只要重寫這個方法,當我們定義的全域變數instance有值得時候,就會直接返回,如果沒有,就會調用父類方法[super allocWithZone:zone]並賦值給instance,但是這時候有一個危險,那就是如果這裡有兩個線程都進來了,那樣就會分配兩次,所以我們要給本段程式加鎖。

+ (id)allocWithZone:(struct _NSZone *)zone {    if (_instance == nil) { // 防止頻繁加鎖        @synchronized(self) {            if (_instance == nil) { // 防止建立多次          _instance = [super allocWithZone:zone];            }        }    }    return _instance;}

提供一個類方法讓外界訪問唯一的執行個體。
跟上面的allocWithzone一樣,不過有所不同的是這裡調用的時【[self alloc] init】方法。

+ (instancetype)sharedMusicTool {    if (_instance == nil) { // 防止頻繁加鎖            @synchronized(self) {            if (_instance == nil) { // 防止建立多次               _instance = [[self alloc] init];            }        }    }    return _instance;}實現copyWithZone:方法- (id)copyWithZone:(struct _NSZone *)zone {    return _instance;}
3:MRC中的單例模式

過程:
非ARC中(MRC),單例模式的實現(比ARC多了幾個步驟)
實現記憶體管理方法。

- (id)retain { return self; }//父類裡面是計數器+1,重寫將不會+1- (NSUInteger)retainCount { return 1; }//父類裡面返回當前對象的計數個數- (oneway void)release {}//父類裡面是計數器-1,重寫將不會-1- (id)autorelease { return self; }//父類裡面記憶體自動管理釋放的,跟記憶體池有關
GCD下完美單例模式(ARC&MRC通吃)判斷ARC的宏

這裡首先要知道一個宏了 __has_feature(objc_arc)

單例模式在ARC\MRC環境下的寫法有所不同,需要編寫2套不同的代碼
可以用宏判斷是否為ARC環境。

#if __has_feature(objc_arc)// ARC#else// MRC#endif
傳值的宏

就一句

#define NYSingletonH(name) + (instancetype)shared##name;

用的時候傳進name,他就會自動替換了。

用GDC運行一次代碼解決

怎麼解決呢 ?其實就是把加鎖換成GCD的一次性代碼

代碼如下:

+(id)allocWithZone:(struct _NSZone *)zone    {        if (_instance == nil) {            static dispatch_once_t onceToken;            dispatch_once(&onceToken, ^{                if (_instance == nil) {                    _instance = [super allocWithZone:zone];                }            });        }        return _instance;    }

捷徑,xcode中只要敲dispatch_once就自動有啦,填填寫寫。

終極方式,以後單例不用敲代碼了,直接掉就行了。

第一步,簡曆一個.h檔案,例如

第二步,檔案中寫入以下代碼:

// .h檔案#define NYSingletonH(name) + (instancetype)shared##name;// .m檔案#define NYSingletonM#if __has_feature(objc_arc)#define NYSingletonM(name)    static id _instance;    +(id)allocWithZone:(struct _NSZone *)zone    {        if (_instance == nil) {            static dispatch_once_t onceToken;            dispatch_once(&onceToken, ^{                if (_instance == nil) {                    _instance = [super allocWithZone:zone];                }            });        }        return _instance;    }    +(instancetype)shared##name    {        if (_instance == nil) {            static dispatch_once_t onceToken;            dispatch_once(&onceToken, ^{                if (_instance == nil) {                    _instance = [[self alloc]init];                }            });        }        return _instance;    }    -(id)copyWithZone:(NSZone *)zone    {        return _instance;\\    }#else#define NYSingletonM(name)    static id _instance;    +(id)allocWithZone:(struct _NSZone *)zone    {        if (_instance == nil) {            static dispatch_once_t onceToken;            dispatch_once(&onceToken, ^{                if (_instance == nil) {                    _instance = [super allocWithZone:zone];                }            });        }        return _instance;    }    +(instancetype)shared##name    {        if (_instance == nil) {            static dispatch_once_t onceToken;            dispatch_once(&onceToken, ^{                if (_instance == nil) {                    _instance = [[self alloc]init];                }            });        }        return _instance;    }    -(id)copyWithZone:(NSZone *)zone    {        return _instance;    }    -(id)retain    {        return self;    }    -(NSUInteger)retainCount{return 1;}    -(oneway void)release{}    -(id)autorelease{return self;}#endif

\符號是讓後面的東東包含到上一行去,因為define只能定義一行。

第三步:在pch檔案中寫入調用代碼:

#import "NYSingleton.h"

第四步:在需要用到的類中調用:

在點h檔案中調用這個

在點m檔案中調用這個

最後調用,還是單例:

補充,自訂宏代替NSLog

注意:開發過程中,會使用NSLog來列印資訊用於調試,但releae的軟體卻不能包含NSLog,可能會有被打回的風險,但是要是全部注釋掉NSLog那太痛苦了,也不利於以後的調試。

下面,我們可以採用自訂宏來取代NSLog,只在我們想要的時候輸出

/* XCode LLVM XXX - Preprocessing中Debug會添加 DEBUG=1 標誌 */#ifdef DEBUG#define NSLog(FORMAT, ...) fprintf(stderr,"%s:%d\t%s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);#else#define NSLog(FORMAT, ...) nil#endif

把以上代碼粘貼到ProjectName-Prefix.pch檔案中。

在調試的時候,會輸出(格式:檔案名稱:行號)日誌。

在Release正式版本的時候,會關閉日誌輸出。

因為XCode LLVM XXX - Preprocessing中Debug會添加 DEBUG=1 標誌。當然我們也能把DEBUG直接換成數字1來設定。

貓貓學iOS(五十二)多線程網路之GCD下單例設計模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.