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

Rya*_*yan 341 singleton objective-c grand-central-dispatch ios

如果您可以定位iOS 4.0或更高版本

使用GCD,它是在Objective C(线程安全)中创建单例的最佳方法吗?

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

Dav*_*ong 215

这是创建类实例的完全可接受且线程安全的方法.它在技术上可能不是"单例"(因为它们只能有1个这样的对象),但只要你只使用该[Foo sharedFoo]方法来访问对象,这就足够了.

  • @samvermette你没有.单身人士的观点是它永远存在.因此,您不释放它,并通过进程退出回收内存. (65认同)
  • @Dave DeLong:在我看来,拥有单身人士的目的并不是其不朽的确定性,而是确定我们有一个实例.如果那个单身人士减少一个信号量怎么办?你不能随意说它会永远存在. (6认同)
  • 你怎么发布它? (4认同)
  • @hooleyhoop是的,在[其文档]中(https://developer.apple.com/library/mac/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/c/func/dispatch_once)."如果同时从多个线程调用,则此函数将同步等待,直到块完成." (4认同)
  • @ WalterMartinVargas-Pena强引用由静态变量持有 (3认同)

Zel*_*lko 36

instancetype

instancetype只是众多语言扩展中的一种Objective-C,每个新版本都添加了更多.

知道它,喜欢它.

并将其作为一个例子,说明如何关注低级细节可以让您深入了解改变Objective-C的强大新方法.

请参考此处:instancetype


+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });    
    return sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)
+ (Class*)sharedInstance
{
    static dispatch_once_t once;
    static Class *sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });    
    return sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)

  • 惊人的提示,谢谢!*instancetype是一个上下文关键字,可用作结果类型,表示方法返回相关的结果类型....*使用instancetype,编译器将正确推断类型. (4认同)
  • 我不清楚这两个片段在这里意味着什么,它们彼此等同吗?一个比另一个更可取?如果作者能对此添加一些解释就太好了。 (3认同)

Ser*_*ruk 33

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 单身人士应该只有一个接入点.这一点是sharedInstance.如果我们在*.h文件中有init方法,那么你可以创建另一个单例实例.这与单身人士的定义相矛盾. (2认同)

小智 6

您可以避免分配类覆盖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;
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ian 5

戴夫是对的,这很好.您可能需要查看Apple关于创建单例的文档,以获取有关实现其他一些方法的提示,以确保在类选择不使用sharedFoo方法时只能创建一个方法.

  • 使用ARC完全无效. (19认同)
  • 呃......这不是创建单身人士的最好例子.不必覆盖内存管理方法. (8认同)