How do I implement an Objective-C singleton that is compatible with ARC?

| | August 7, 2015

How do I convert (or create) a singleton class that compiles and behaves correctly when using automatic reference counting (ARC) in Xcode 4.2?

6 Responses to “How do I implement an Objective-C singleton that is compatible with ARC?”

  1. #import <Foundation/Foundation.h>
    
    @interface SingleTon : NSObject
    
    @property (nonatomic,strong) NSString *name;
    +(SingleTon *) theSingleTon;
    
    @end
    
    #import "SingleTon.h"
    @implementation SingleTon
    
    +(SingleTon *) theSingleTon{
        static SingleTon *theSingleTon = nil;
    
        if (!theSingleTon) {
    
            theSingleTon = [[super allocWithZone:nil] init
                         ];
        }
        return theSingleTon;
    }
    
    +(id)allocWithZone:(struct _NSZone *)zone{
    
        return [self theSingleTon];
    }
    
    -(id)init{
    
        self = [super init];
        if (self) {
            // Set Variables
            _name = @"Kiran";
        }
    
        return self;
    }
    
    @end
    

    Hope above code will help it out.

  2. In exactly the same way that you (should) have been doing it already:

    + (instancetype)sharedInstance
    {
        static MyClass *sharedInstance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedInstance = [[MyClass alloc] init];
            // Do any other initialisation stuff here
        });
        return sharedInstance;
    }
    
  3. Igor Fedorchuk on November 30, -0001 @ 12:00 AM

    This is a version for ARC and non-ARC

    How To use:

    MySingletonClass.h

    @interface MySingletonClass : NSObject
    
    +(MySingletonClass *)sharedInstance;
    
    @end
    

    MySingletonClass.m

    #import "MySingletonClass.h"
    #import "SynthesizeSingleton.h"
    @implementation MySingletonClass
    SYNTHESIZE_SINGLETON_FOR_CLASS(MySingletonClass)
    @end
    
  4. This is my pattern under ARC.
    Satisfies new pattern using GCD and also satisfies Apple’s old instantiation prevention pattern.

    @implementation AAA
    + (id)alloc
    {
        return  [self allocWithZone:nil];
    }
    + (id)allocWithZone:(NSZone *)zone
    {
        [self doesNotRecognizeSelector:_cmd];
        abort();
    }
    + (instancetype)theController
    {
        static AAA* c1  =   nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^
        {
            c1  =   [[super allocWithZone:nil] init];
    
            // For confirm...       
            NSLog(@"%@", NSStringFromClass([c1 class]));    //  Prints AAA
            NSLog(@"%@", @([c1 class] == self));            //  Prints 1
    
            Class   real_superclass_obj =   class_getSuperclass(self);
            NSLog(@"%@", @(real_superclass_obj == self));   //  Prints 0
        });
    
        return  c1;
    }
    @end
    
  5. Alternatively, Objective-C provides the +(void)initialize method for NSObject and all its sub-classes. It is always called before any methods of the class.

    I set a breakpoint in one once in iOS 6 and dispatch_once appeared in the stack frames.

  6. if you want to create other instance as needed.do this:

    + (MyClass *)sharedInstance
    {
        static MyClass *sharedInstance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedInstance = [[MyClass alloc] init];
            // Do any other initialisation stuff here
        });
        return sharedInstance;
    }
    

    else,you should do this:

    + (id)allocWithZone:(NSZone *)zone
    {
        static MyClass *sharedInstance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedInstance = [super allocWithZone:zone];
        });
        return sharedInstance;
    }
    

Leave a Reply