在開發中經常會用到單例,它在整個程序的運行週期裏面只會被創建一次,只要程序沒有結束,它就不會被釋放!創建單例的兩種方式如下:
一、GCD方式創建單例
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToke;
dispatch_once(&onceToke, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
return _instance;
}
- (id)copyWithZone:(NSZone *)zone
{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
二、互鎖創建單例的方法
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
+ (instancetype)sharedInstance
{
@synchronized(self) {
if (_instance == nil) {
_instance = [[self alloc] init];
}
}
return _instance;
}
- (id)copyWithZone:(NSZone *)zone
{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
說明:
1、CGD創建單例的方式中,用dispatch_once保證了裏面的代碼只能被執行一次,如果程序再次走到這個方法的時候會直接返回創建好的實例對象,這樣保證了只會創建一個實例對象;
2、 在互鎖創建單例的方式中,@synchronized相當於給括起來的任務加了一把鎖,如果當前任務正在執行,另外一條線程執行到@synchronized時候就會進入睡眠模式,等當前任務執行完後纔會執行,此時_instance已經被創建,不爲nil,所以直接返回_instance,這樣也保證了只會創建一個實例對象。但是在多線程開發中,這種方式會影響程序的性能,建議用第一種
總結:
在多線程開發中互鎖的方式會影響項目的性能,建議用GCD的方式!
通過GCD創建單例的方式是固定不變的,爲了方便以後快速實現單例,可以把創建方式定義成宏。
// .h文件
#define singleton_h(name) + (instancetype)shared##name;
// .m文件
#define singleton_m(name) \
static id _instance; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[self alloc] init]; \
}); \
return _instance; \
} \
\
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instance; \
}\
\
- (id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}