iOS開發(fā)之單例

由于iOS開發(fā)中經(jīng)常會用到單例,所以就做個簡單的總結(jié)。

單例模式
  • 作用:
    可以保證在程序運行過程中,一個類只有一個實例,而且該實例易于供外界訪問,從而方便的控制了實例個數(shù),并節(jié)約系統(tǒng)資源
  • 使用場合:
    在整個應(yīng)用程序中,共享一份資源(這份資源只需要創(chuàng)建初始化一次)

arc環(huán)境下實現(xiàn)單例模式

#import <Foundation/Foundation.h>
//重寫copy的相關(guān)方法時必須引入copy的相關(guān)文件
@interface danli : NSObject<NSCopying,NSMutableCopying>

//類方法
//1.方便訪問
//2.標(biāo)明身份
//3.命名規(guī)范 share/default + 類名
+(instancetype)shareDanli;

@end
#import "danli.h"

@implementation danli

//0.提供全局變量
static danli *_instance;
//1.alloc
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //method 1
    //加互斥鎖解決多線程訪問安全問題
    @synchronized(self){
       
        if (_instance==nil) {
            _instance=[super allocWithZone:zone];
        }
    }
    
    //method 2
    //本身就是線程安全的,不需要擔(dān)心多線程安全問題
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance=[super allocWithZone:zone];
    });
    
    return _instance;
}
//2.提供類方法
+(instancetype)shareDanli{
    return [[self alloc]init];
}
//3.嚴(yán)謹(jǐn),因為有的時候不止是alloc或new方法創(chuàng)建
-(id)copyWithZone:(NSZone *)zone{
    return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
    return _instance;
}
@end

以上就是在arc的環(huán)境下構(gòu)建單例的方法,mrc的環(huán)境下構(gòu)建單例的方法差不多,就是多重寫幾個方法

mrc環(huán)境下實現(xiàn)單例模式

首先,設(shè)置一下mrc的開發(fā)環(huán)境,如下圖所示


屏幕快照 2018-05-04 下午2.56.09.png

其次,因為在mrc環(huán)境下需要在創(chuàng)建實例后進行release操作,但這顯然和單例的目標(biāo)相違背,所以為了不進行銷毀,我們可以重寫以下方法,

-(oneway void)release{
}
-(instancetype)retain{
    return _instance;
}
-(NSUInteger)retainCount{
    return MAXFLOAT;
}

這樣就已經(jīng)實現(xiàn)了我們的目標(biāo)

但是考慮到如果經(jīng)常切換mrc和arc的環(huán)境,我們就需要經(jīng)常修改相關(guān)方法,所以為了解決這個問題,我們可以使用條件編譯來動態(tài)的根據(jù)開發(fā)環(huán)境來進行mrc和arc的不同考慮,也就是將mrc的相關(guān)代碼放在條件編譯的else語句中,這樣也就不需要經(jīng)常修改代碼了

//條件編譯
#if __has_feature(objc_arc)
//arc
#else
//mrc
-(oneway void)release{
}
-(instancetype)retain{
    return _instance;
}
-(NSUInteger)retainCount{
    return MAXFLOAT;
}
#endif

以上已經(jīng)完成了單例的操作,但是在一個大的項目中,我們肯定不會只有一個單例,而單例的代碼其實也都差不多,如果每次都進行復(fù)制,在代碼的復(fù)用問題上又做的不是很好,所以我們可以考慮將單例的代碼寫成宏,這樣就可以方便使用了,其中,這里使用了帶參數(shù)的宏,參數(shù)即為name,也就是我們自己設(shè)置的單例名稱

  • 定義.h文件的宏
#define singerH(name) +(instancetype)share##name;
  • 定義.m文件的宏,其中也是使用條件編譯區(qū)分arc和mrc的開發(fā)環(huán)境
#if __has_feature(objc_arc)
//arc
#define singerM(name) static id *_instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
@synchronized(self){\
if (_instance==nil) {\
_instance=[super allocWithZone:zone];\
}\
}\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance=[super allocWithZone:zone];\
});\
return _instance;\
}\
+(instancetype)share##name{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone{\
return _instance;\
}\
-(id)mutableCopyWithZone:(NSZone *)zone{\
return _instance;\
}
#else
//mrc
#define singerM(name) static id *_instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
@synchronized(self){\
if (_instance==nil) {\
_instance=[super allocWithZone:zone];\
}\
}\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance=[super allocWithZone:zone];\
});\
return _instance;\
}\
+(instancetype)share##name{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone{\
return _instance;\
}\
-(id)mutableCopyWithZone:(NSZone *)zone{\
return _instance;\
}\
-(oneway void)release{\
}\
-(instancetype)retain{\
    return _instance;\
}\
-(NSUInteger)retainCount{\
    return MAXFLOAT;\
}\
#endif

在使用時,只要在自己創(chuàng)建的單例文件中調(diào)用相關(guān)的參數(shù)宏就可以了

以上,就是iOS開發(fā)中單例的相關(guān)使用方法

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

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

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