@synchronized
定義一個靜態(tài)的全局的變量
static Settings *sharedSettings = nil;
創(chuàng)建一個類方法,用來返回該類實例
synchronized
這個主要是考慮多線程的程序,這個指令可以將{ } 內的代碼限制在一個線程執(zhí)行,如果某個線程沒有執(zhí)行完盐类,其他的線程如果需要執(zhí)行就得等著赋铝。
+ (Settings *)sharedInstance {
@synchronized(self){
if(sharedSettings == nil){
sharedSettings = [[self alloc] init];
//做一些初始化操作
}
}
return sharedSettings;
}
- 重寫allocWithZone方法,用來保證其他人直接使用alloc和init試圖獲得一個新實力的時候不產生一個新實例迁杨,
+ (id)allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (sharedSettings == nil) {
sharedSettings = [super allocWithZone:zone];
}
}
return sharedSettings;
}
dispatch_once
有些變量只需要初始化一次(如從文件中讀取配置參數诗眨,讀取設備型號等等)唉匾,可以使用dispatch_once來進行讀取優(yōu)化,保證只調用API一次匠楚,以后就只要直接訪問變量即可
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
dispatch_once不僅意味著代碼僅會被運行一次巍膘,而且還是線程安全的,這就意味著你不需要使用諸如
@synchronized
之類的來防止使用多個線程或者隊列時不同步的問題芋簿。
//范例如下:
static BOOL isTestMode;
+ (BOOL)isTestMode {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSNumber* obj = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFResourceTest"];
isTestMode = [obj boolValue];
});
return isTestMode;
}
實際要如何使用這些呢?
好吧峡懈,假設有一個AccountManager類,你想在整個應用中訪問該類的共享實例与斤。你可以按如下代碼簡單實現一個類方法:
+ (AccountManager *)sharedManager {
static AccountManager *sharedAccountManagerInstance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedAccountManagerInstance = [[self alloc] init];
});
return sharedAccountManagerInstance;
}
這就意味著你任何時候訪問共享實例逮诲,需要做的僅是:
AccountManager *accountManager = [AccountManager sharedManager];
該方法有很多優(yōu)勢 |
---|
a. 線程安全 |
b. 很好滿足靜態(tài)分析器要求 |
c. 和自動引用計數(ARC)兼容 |
d. 僅需要少量代碼 |
就這些,你現在在應用中就有一個共享的實例幽告,該實例只會被創(chuàng)建一次。
該方法有很多優(yōu)勢 |
---|
a. 線程安全 |
b. 很好滿足靜態(tài)分析器要求 |
c. 和自動引用計數(ARC)兼容 |
d. 僅需要少量代碼 |
該方法的劣勢就是它仍然運行創(chuàng)建一個非共享的實例:我們通常在OC中實現一個單例方法都是這樣:
static HLTestObject *instance = nil;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
});
return instance;
}
可是這樣就可以了么裆甩?我做了如下測試:
HLTestObject *objct1 = [HLTestObject sharedInstance];
NSLog(@"%@",objct1);
HLTestObject *objc2 = [[HLTestObject alloc] init];
NSLog(@"%@",objc2);
HLTestObject *objc3 = [HLTestObject new];
NSLog(@"%@",objc3);
看到這個測試冗锁,你想到打印結果了么?結果是這樣的:
2016-05-23 12:52:57.095 PractiseProject[3579:81998] <hltestobject: 0x7fcf39515510>
2016-05-23 12:52:57.095 PractiseProject[3579:81998] <hltestobject: 0x7fcf395c4b70>
2016-05-23 12:52:57.095 PractiseProject[3579:81998] <hltestobject: 0x7fcf395c6890></hltestobject: 0x7fcf395c6890></hltestobject: 0x7fcf395c4b70></hltestobject: 0x7fcf39515510>
很明顯嗤栓,通過三種方式創(chuàng)建出來的是不同的實例對象冻河,這就違背了單例類有且僅有一個實例的定義。
為了防止別人不小心利用alloc/init方式創(chuàng)建示例茉帅,也為了防止別人故意為之叨叙,我們要保證不管用什么方式創(chuàng)建都只能是同一個實例對象,這就得重寫另一個方法堪澎,實現如下:
static TYGAreaPickerView *sharedObject = nil;
+ (TYGPlaceholderHelper *)sharedInstance {
static dispatch_once_t _singletonPredicate;
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
return sharedObject;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedInstance];
}
static HLTestObject *instance = nil;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
instance.height = 10;
instance.object = [[NSObject alloc] init];
instance.arrayM = [[NSMutableArray alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
static HLTestObject *instance = nil;
+ (instancetype)sharedInstance {
return [[self alloc] init];
}
- (instancetype)init {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super init];
instance.height = 10;
instance.object = [[NSObject alloc] init];
instance.arrayM = [[NSMutableArray alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}