我对单例初始化的理解是否正确?

时间:2017-02-15 22:32:41

标签: objective-c multithreading initialization singleton grand-central-dispatch

我有一个单身声明如下:

@interface SomeGlobalData : NSObject
+ (instancetype) sharedInstance;

@property (nonatomic, assign) BOOL              info;

@end

@implementation SomeGlobalData

+(instancetype)sharedInstance
{
    static SomeGlobalData *sharedObj = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedObj = [[self alloc] init];
    });
    return sharedObj;
}

-(id)init 
{
      if (self = [super init]) {
         info = false;
      }
  return self;
}
@end

-(void)_startSomeMethod
{
       SomeGlobalData *obj = [SomeGlobalData sharedInstance];

       //do stuff

      obj.info = true;
}
-(void)_readStatus 
{
       SomeGlobalData *data = [SomeGlobalData sharedInstance];
       NSLog(@"Start status = %d", data.info);
}
 -(void)_dummyMethodForUnderstanding 
{
       [self  _readStatus];
       [self  _startSomeMethod];
       [self  _readStatus];
}

调用dummyMethodForUnderstanding的输出应为

Start status = 0
Start status = 1

我对单身人士课程的理解是否正确?我担心每次调用sharedInstance方法时都会调用init,我可能最终意外地重新初始化infofalse

2 个答案:

答案 0 :(得分:1)

由于各种原因,这很可能不应该是单身人士。主要是因为如果你尝试加密两个项目,一个接一个地加密,即使在简单的情况下它也会失败。如果两个线程同时尝试加密,情况会更糟。

[[EncryptedData alloc] init]只会调用一次,因为它是一个单例。但它不能作为单例工作,只需删除sharedInstance并在需要EncrypedData对象时调用alloc / init。

Singleton的规则可以从“Highlander” - “只能是一个人”和“谁想永远活着” - 当然是单身人士。由于只能有一个,它不能保持单身人士的两个用户的状态。 _encryptComplete是状态每次加密。单身人士无法正确处理此问题。

答案 1 :(得分:1)

  

我担心每次调用sharedInstance方法时都会调用init,我可能最终意外地将info重新初始化为false

不,dispatch_once的全部目的是闭包内的代码只会被调用一次。对sharedInstance的后续调用不会再次调用您的init方法。后来对info的调用不会影响您的sharedInstance媒体资源。

顺便说一句,你描述了预期的输出“应该是什么”。我们是否从这个评论推断出这不是你的输出实际上是什么?如果你两次都看到“status = 0”,那么我可能会怀疑省略的“do stuff”代码可能正在做异步或类似的事情。但问题不在于多次调用dispatch_once块。

顺便说一句,你问题原始演绎的加密算法不适合成为单身人士。有关单身人士的限制/考虑因素的更广泛讨论,请参见What is so bad about singletons?;我们不需要在这里重复一遍。