在Objective C中使用GCD的dispatch_once创build单例

如果你可以瞄准iOS 4.0或以上

使用GCD,在目标C(线程安全)中创build单例的最好方法是什么?

+ (instancetype)sharedInstance { static dispatch_once_t once; static id sharedInstance; dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } 

这是一个完全可以接受和线程安全的方式来创build你的类的一个实例。 它在技术上可能不是一个“单身”(因为这些对象只能有一个),但只要你使用[Foo sharedFoo]方法来访问对象,这就足够了。

instancetype

instancetypetypes只是Objective-C的许多语言扩展之一,每个新版本都增加了更多。

知道它,爱它。

并以此为例,说明如何关注低级细节,让您深入了解强大的Objective-C转换新方法。

请参阅这里:instancetype


 + (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

 @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 

戴夫是正确的,这是完全正确的。 你可能想看看苹果公司的文档创build一个单身人士提供实施一些其他方法的提示,以确保只有一个可以创build如果类select不使用sharedFoo方法。

你可以避免这个类被覆盖alloc方法。

 @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; } 

如果你想确保[[MyClass alloc] init]返回与sharedInstance相同的对象(在我看来不是必要的,但有些人想要它),那么使用第二个dispatch_once可以非常容易和安全地完成:

 - (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方法中。 任何稍后调用init将完全忽略返回的alloc,并返回相同的sharedInstance; alloc的结果将被释放。

+ sharedInstance方法将像以往一样工作。 如果它不是调用[[MyClass alloc] init]的第一个调用者,那么init的结果不是alloc调用的结果,但是这是正确的。

要创build线程安全的单例,你可以这样做:

 @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单身人士非常好的单身人士

 //Create Singleton +( instancetype )defaultDBManager { static dispatch_once_t onceToken = 0; __strong static id _sharedObject = nil; dispatch_once(&onceToken, ^{ _sharedObject = [[self alloc] init]; }); return _sharedObject; } //In it method -(instancetype)init { self = [super init]; if(self) { //Do your custom initialization } return self; }