什么是單例模式?
單例模式是一種常用的軟件設(shè)計模式??梢员WC通過單例模式可以保證系統(tǒng)中一個類只有一個實(shí)例而且該實(shí)例易于外界訪問,從而方便對實(shí)例個數(shù)的控制并節(jié)約系統(tǒng)資源。
為什么要使用單例模式?
如果我們希望在系統(tǒng)中某個類的對象只能存在一個,單例模式是最好的解決方案。
怎么使用單例模式?
單例模式可以分為餓漢式和懶漢式,在iOS中我們經(jīng)常使用的是懶漢式,下面我們看看怎么日常開發(fā)中怎么運(yùn)用單例模式。
-
第一種寫法:
+ (id)sharedInstance { static testClass *sharedInstance = nil; // 為了在多線程中也保證只產(chǎn)生一個實(shí)例,加上線程同步鎖 @synchronized(self) { if (!sharedInstance) { sharedInstance = [[self alloc] init]; } } return sharedInstance; } -
第二種寫法:
+ (instancetype)shareTools { return [[self alloc] init]; } + (instancetype)allocWithZone:(struct _NSZone *)zone { // 注意: 單例是不可以繼承的, 如果繼承引發(fā)問題 // 如果先創(chuàng)建父類, 那么永遠(yuǎn)都是父類 // 如果先創(chuàng)建子類, 那么永遠(yuǎn)都是子類 static id instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [super allocWithZone:zone]; }); return instance; }
注意:同時,我們還要重寫copyWithZone,mutableCopyWithZone和非ARC的方法release,retain,retainCount。
抽取單例宏
由于單例模式在我們的日常開發(fā)中使用頻率非常高,為了提高代碼的復(fù)用性,我們可以將單例模式的代碼抽取成一個宏,這樣以后使用的時候可以用宏快速實(shí)現(xiàn)單例模式。
將下面的代碼寫到Singleton.h文件中,以后用到單例的時候,直接將Singleton.h添加到項目中即可快速實(shí)現(xiàn)單例。
使用方法:在要實(shí)現(xiàn)單例類的.h文件聲明中寫下SingleInterface(*name*),.m文件中SingleImplementation(*name*),就實(shí)現(xiàn)了單例模式。
#define SingleInterface(name) +(instancetype)share##name
#if __has_feature(objc_arc)
// ARC
#define SingleImplementation(name) +(instancetype)share##name \
{ \
return [[self alloc] init]; \
} \
static id _instance; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return self; \
}
#else
// MRC
#define SingleImplementation(name) +(instancetype)share##name \
{ \
return [[self alloc] init]; \
} \
static id _instance; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return self; \
} \
- (oneway void)release \
{} \
- (instancetype)retain \
{ \
return self; \
} \
- (NSUInteger)retainCount \
{ \
return MAXFLOAT; \
}
#endif```