BeachRunnerFred
BeachRunnerFred

Reputation: 18558

Should I be storing a singleton as an ivar?

I'm creating a wrapper class for an existing singleton class. Since I'll be accessing the singleton several times, I'd like to store it as an ivar in my wrapper class...

@interface WrapperClass () 

@property (nonatomic, strong) SingletonClass singletonObj;

@end

...so that I don't have to constantly write [[SingletonClass sharedInstance] methodName]. Instead I can write [singletonObj methodName]. It just feels cleaner to me.

I'm new to iOS development, so I'm wondering if there's anything fundamentally wrong with this approach.

Also, with ARC, should I be storing the singleton with a strong reference?

Upvotes: 0

Views: 201

Answers (3)

lonlywolf
lonlywolf

Reputation: 505

You can just define a macros, like this:

#define _SINGLETON(method) { [[SingletonClass sharedManager] method]; }

Then you can use it in your code like this:

_SINGLETON(methodName);

You can define this macros in the SingletonClass.h, and then you will have possibility to use it anywhere, there your header is imported. This way you don't need to think about iVars.

Upvotes: 0

Paul.s
Paul.s

Reputation: 38728

Unless your doing something crazy the likelihood is the extra retain/release should cause no issue.

Therefore there is no real issue with storing it in an ivar...

A better reason for doing this would not be to save your typing but to improve the testability /reusability of the class. By making it an ivar it allows you to inject a different class in to change the behaviour.

I would consider making an accessor that will by default give me the singleton but still allow me to inject a different class if I choose like this

- (SingletonClass *)singletonObj;
{
  return _singletonObj = _singletonObj ?: [SingletonClass sharedInstance];
}

Update:

It's also worth thinking about "why would you make using this singleton different from using an ivar?". If you use it throughout your class like it was an ivar then why do you access it in a completely different way?

For example often when I use a managedObjectContext there is only one in my whole app. A lot of people use the app delegate as a singleton and access it that way but I prefer to pass it along as an ivar. Conceptually the managedObjectContext is just another object that I am using like any other ivar so why should I have to mentally switch how I access it?

This is bad

[(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];

Good

self.managedObjectContext;

This now gives me two advantages.

  1. If my class is littered with calls to [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; then it is hard to rip it out of this project and place it in another without a risky search and replace. If I access the singleton in one place the "accessor" then I only have one place to change the code.

  2. In my production app I probably want my data to be persistant so I would give the object access to a managedObjectContext with a persistant store, whereas in my tests I don't want state to be persisted between tests so I would give the object a non persistant store instead.

Upvotes: 2

Gabriele Petronella
Gabriele Petronella

Reputation: 108101

It makes sense. Just initialize your singleton and store it in the ivar. That said, your code is actually defining a property, which is not the same thing of an ivar.

For instance you could define your singleton i var like follows

@implementation WrapperClass {
    SingletonClass * _singleton;
}

and then initialize the singleton in the default constructor

- (id)init {
    self = [super init];
    if (self) {
        //...
        _singleton = [SingletonClass sharedInstance];
        //...
    }
    return self;
}

Upvotes: 1

Related Questions