2

When we write a non-ARC code in order to create a singleton class, it goes something like this:

myclass * myc_ins = nil;
@implementation myclass
+(myclass *) getInstance {
    if(!myc_ins) 
        myc_ins = [[myclass alloc] init];
    return myc_ins;
}
// ...

BUT, if same code is written in ARC, it releases the object and when getInstance is called after some time, it returns some dangling pointer as the memory being pointed to is freed. Also, I have seen this code for ARC apps:

myclass *_instance = nil;
+ (myclass *)sharedInstance {
    static dispatch_once_t _onceToken = 0;
    dispatch_once(&_onceToken, ^{
        myclass = [[myclass alloc] init];
    });
    return _instance;
}

Although the code inside dispatch_once gets executed once, how does in this case the compiler know to retain the _instance variable?

Nero
  • 1,295
  • 1
  • 16
  • 23
Praveen
  • 419
  • 3
  • 14
  • 3
    I disagree that arc will destroy the singleton given there is still a reference to the object. Can you back that statement up? – Droppy May 03 '14 at 09:03

3 Answers3

3

In ARC defenition myclass *_instance; mean strong reference at myclass objects. So every assignment to _instance will retain object. And there is litle correction of yours code:

static myclass *_instance = nil;

+ (myclass *)sharedInstance {
    static dispatch_once_t _onceToken = 0;
    dispatch_once(&_onceToken, ^{
       _instance = [[myclass alloc] init];
       });
    return _instance;
}
Cy-4AH
  • 4,370
  • 2
  • 15
  • 22
1

I think it should be:

static myclass *_instance = nil;

and because it is a global it is not released (until program termination).

valfer
  • 3,545
  • 2
  • 19
  • 24
  • It _must_ be static. Otherwise, if you use the same pattern in a different file for a different singleton object, there will be only one extern variable, so one singleton overwrites the other one. It would be best to have the static variable inside the sharedInstance method, so there is guaranteed no other way to read it than through sharedInstance. – gnasher729 Aug 03 '14 at 16:06
1

You should change

myclass *_instance = nil;

to

static myclass *_instance = nil;

and

myclass = [[myclass alloc] init];

to

_instance = [[myclass alloc] init];

Hope this help.

Useful related stackoverflow question here

Community
  • 1
  • 1
Roland Kákonyi
  • 583
  • 4
  • 12