由于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)境,如下圖所示

其次,因為在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)使用方法