Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么苹果建议使用dispatch_一次性实现ARC下的单例模式?_Ios_Objective C_Singleton_Automatic Ref Counting - Fatal编程技术网

Ios 为什么苹果建议使用dispatch_一次性实现ARC下的单例模式?

Ios 为什么苹果建议使用dispatch_一次性实现ARC下的单例模式?,ios,objective-c,singleton,automatic-ref-counting,Ios,Objective C,Singleton,Automatic Ref Counting,在ARC下的单例共享实例访问器中使用dispatch_一次的确切原因是什么 + (MyClass *)sharedInstance { // Static local predicate must be initialized to 0 static MyClass *sharedInstance = nil; static dispatch_once_t onceToken = 0; dispatch_once(&onceToken, ^{

在ARC下的单例共享实例访问器中使用dispatch_一次的确切原因是什么

+ (MyClass *)sharedInstance
{
    //  Static local predicate must be initialized to 0
    static MyClass *sharedInstance = nil;
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyClass alloc] init];
        // Do any other initialisation stuff here
    });
    return sharedInstance;
}
在后台异步实例化单例不是一个坏主意吗?我的意思是,如果我请求共享实例并立即依赖它,但dispatch_在圣诞节之前创建我的对象会发生什么?它不会马上回来,对吗?至少这似乎是中央大调度的全部要点


那么他们为什么要这样做呢?

因为它只运行一次。因此,如果您尝试从不同的线程访问它两次,则不会导致问题

迈克·阿什在他的博客文章中有一个完整的描述

并非所有GCD块都是异步运行的。

dispatch\u once()
是绝对同步的。并非所有GCD方法都是异步的(例如,
dispatch\u sync()
是同步的)。使用
dispatch\u once()
替换了以下习惯用法:

+ (MyClass *)sharedInstance {
    static MyClass *sharedInstance = nil;
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[MyClass alloc] init];
        }
    }
    return sharedInstance;
}

dispatch\u once()
的优点是速度更快。它在语义上也更清晰,因为它还可以防止多个线程执行sharedInstance的alloc init——如果它们都在同一时间尝试的话。它不允许创建两个实例。
dispatch\u once()
的整个思想是“执行某件事情一次且仅执行一次”,这正是我们正在做的。

为了论证,我需要注意的是,这并不是说它是同步执行的。它只说多个同时调用将被序列化。您声称它更快-快多少?我没有理由认为你没有说实话,但我希望看到一个简单的基准测试。我刚刚做了一个简单的基准测试(在iPhone 5上),看起来dispatch_once比@synchronized快2倍左右。@ReneDohan:如果你100%确定没有人从其他线程调用该方法,那么它就可以工作了。但是使用<代码> TexChyOnCuthor()/Case>非常简单(特别是因为XCODER甚至会自动将其完整化为您的代码片段),并且意味着您甚至不必考虑该方法是否需要线程安全。@思英:事实上,这不是真的。首先,在
+initialize
中完成的任何操作都会在类被触动之前发生,即使您还没有尝试创建共享实例。一般来说,延迟初始化(仅在需要时创建)更好。第二,即使是你的性能声明也不正确
dispatch_once()
所用的时间几乎与在
+initialize
中说
if(self==[MyClass])
所用的时间完全相同。如果您已经有了一个
+initialize
,那么是的,在那里创建共享实例会更快,但大多数类没有。
注意:静态变量和全局变量默认为零。
莉莉的答案更好,但我将留下我的,以保留指向Mike Ash帖子的链接。