若是您能夠定位iOS 4.0或更高版本 安全
使用GCD,這是在Objective-C(線程安全)中建立單例的最佳方法嗎? ide
+ (instancetype)sharedInstance { static dispatch_once_t once; static id sharedInstance; dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; }
您能夠經過覆蓋alloc方法避免分配類。 spa
@implementation MyClass static BOOL useinside = NO; static id _sharedObject = nil; +(id) alloc { if (!useinside) { @throw [NSException exceptionWithName:@"Singleton Vialotaion" reason:@"You are violating the singleton class usage. Please call +sharedInstance method" userInfo:nil]; } else { return [super alloc]; } } +(id)sharedInstance { static dispatch_once_t p = 0; dispatch_once(&p, ^{ useinside = YES; _sharedObject = [[MyClass alloc] init]; useinside = NO; }); // returns the same object each time return _sharedObject; }
instancetype
只是Objective-C
的許多語言擴展之一,每一個新發行版都添加了更多擴展。 線程
知道,愛它。 code
並以它爲例,說明如何關注底層細節能夠使您洞悉轉換Objective-C的強大新方法。 orm
+ (instancetype)sharedInstance { static dispatch_once_t once; static id sharedInstance; dispatch_once(&once, ^ { sharedInstance = [self new]; }); return sharedInstance; }
+ (Class*)sharedInstance { static dispatch_once_t once; static Class *sharedInstance; dispatch_once(&once, ^ { sharedInstance = [self new]; }); return sharedInstance; }
MySingleton.h get
@interface MySingleton : NSObject +(instancetype)sharedInstance; +(instancetype)alloc __attribute__((unavailable("alloc not available, call sharedInstance instead"))); -(instancetype)init __attribute__((unavailable("init not available, call sharedInstance instead"))); +(instancetype)new __attribute__((unavailable("new not available, call sharedInstance instead"))); -(instancetype)copy __attribute__((unavailable("copy not available, call sharedInstance instead"))); @end
MySingleton.m 博客
@implementation MySingleton +(instancetype)sharedInstance { static dispatch_once_t pred; static id shared = nil; dispatch_once(&pred, ^{ shared = [[super alloc] initUniqueInstance]; }); return shared; } -(instancetype)initUniqueInstance { return [super init]; } @end
若是要確保[[MyClass alloc] init]返回與sharedInstance相同的對象(我認爲這不是必需的,可是有些人想要),則能夠使用第二個dispatch_once輕鬆,安全地完成此操做: it
- (instancetype)init { static dispatch_once_t once; static Class *sharedInstance; dispatch_once(&once, ^ { // Your normal init code goes here. sharedInstance = self; }); return sharedInstance; }
這容許[[MyClass alloc] init]和[MyClass sharedInstance]的任何組合返回相同的對象。 [MyClass sharedInstance]會更有效率。 工做原理:[MyClass sharedInstance]將調用一次[[MyClass alloc] init]。 其餘代碼也能夠屢次調用它。 初始化的第一個調用者將執行「常規」初始化,並將單例對象存儲在init方法中。 之後對init的任何調用都將徹底忽略返回的alloc並返回相同的sharedInstance; alloc的結果將被釋放。
+ sharedInstance方法將一如既往地工做。 若是不是第一個調用[[MyClass alloc] init]的調用者,則init的結果不是alloc調用的結果,可是能夠。
要建立線程安全單例,您能夠執行如下操做:
@interface SomeManager : NSObject + (id)sharedManager; @end /* thread safe */ @implementation SomeManager static id sharedManager = nil; + (void)initialize { if (self == [SomeManager class]) { sharedManager = [[self alloc] init]; } } + (id)sharedManager { return sharedManager; } @end
這個博客很好地解釋了objc / cocoa中的單例