1

I have a singleton declaration as follows :

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

The output of calling dummyMethodForUnderstanding should be

Start status = 0
Start status = 1

Is my understanding of singleton classes correct? I am worried that init is called every time sharedInstance method gets called and I might end up accidentally re-initializing info to false

ExceptionHandler
  • 213
  • 1
  • 8
  • 24

2 Answers2

1

It is most likely that this should not be a singleton class, for various reasons. Mostly because it will fail even in the simple case if you try to encrypt two items, one after the other. It's even worse if two threads try to encrypt at the same time.

[[EncryptedData alloc] init] will be called only once, that's because it is a singleton. But it doesn't work as a singleton, just remove sharedInstance and call alloc/init when you need an EncrypedData object.

The rules for Singleton can be taken from "Highlander" - "There Can Only Be One", and "Who Wants To Live Forever" - the singleton of course. Since there can only be one, it cannot hold status for two users of the singleton. _encryptComplete is status per encryption. A singleton cannot handle this correctly.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • It's not clear to me, what has the singleton initialization got anything to do with encryption failing? Also what do you mean by remove alloc/init? Isn't it a possibility that another method could directly invoke `startEncrypt` without invoking `readEncryptStatus` first? – ExceptionHandler Feb 15 '17 at 22:58
  • You encrypt. status = encryptComplete. You try to encrypt again - status is encryptComplete even when the second encryption isn't finished yet. A singleton is absolutely unsuitable when you need status per user of the singleton. And I said remove sharedInstance - call alloc/init instead. – gnasher729 Feb 15 '17 at 23:01
  • Right, but assume that in this case I want to send the same value to every single user. – ExceptionHandler Feb 15 '17 at 23:03
  • @Rob updated the question to remove unnecessary info. I really want to understand and learn the context of singleton. I don't want the answer to focus on "do you need singleton?". I would much rather focus on the usage – ExceptionHandler Feb 15 '17 at 23:25
1

I am worried that init is called every time sharedInstance method gets called and I might end up accidentally re-initializing info to false.

No, the entire purpose of dispatch_once is that the code inside the closure will get called once and only once. Subsequent calls to sharedInstance will not call your init method again. Your info property will not be affected by subsequent calls to sharedInstance.

BTW, you describe what the expected output "should be". Do we infer from this comment that this is not what your output actually is? If you're seeing "status = 0" both times, then I might suspect that the omitted "do stuff" code might be doing something asynchronous or something like that. But the problem is not a result of the dispatch_once block being called multiple times.


As an aside, the encryption algorithm of the original rendition of your question is not a good candidate for being a singleton. See What is so bad about singletons? for broader discussion about the limitations/considerations regarding singleton; we don't need to repeat that here.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044