0

I want to have one object that is initialized in the delegate and I want to be able to use this object anywhere across view controllers (doesn't depend on what view I am currently at). I am guessing the solution to this would be to have a singleton class, so far I have the following:

@interface LocationManager : NSObject <CLLocationManagerDelegate>{
    NSDate *enter;
    NSDate *exit;
    CLLocationManager * manager;

}

@property (nonatomic, retain) NSDate * enter;
@property (nonatomic, retain) NSDate * exit;

- (BOOL)registerRegionWithLatitude:(double)latitude andLongitude:(double)longitude;
+ (LocationManager *)instance;

@end


#import "LocationManager.h"

@implementation LocationManager
@synthesize enter;
@synthesize exit;

#pragma mark - CLLocationManager delegate
static LocationManager *gInstance = NULL;


+ (LocationManager *)instance
{
    @synchronized(self)
    {
        if (gInstance == NULL)
            gInstance = [[self alloc] init];
    }
    return(gInstance);
}

@end

Is this correct? So all I need to do to access this is just to call instance? Inside LocationManager I also want to have only one CLLocationManager, called manager.. however, where do I initialize it so I only have one? Can I do the following? Most other singleton examples doesn't have any variables in the class, so that's where I got confused

+ (LocationManager *)sharedLocationManager
{
    @synchronized(self)
    {
        if (lm == NULL){
            lm = [[self alloc] init];
            lm.manager = [[CLLocationManager alloc] init];
            lm.manager.delegate = lm;
        }
    }
    return(lm);
}
aherlambang
  • 14,290
  • 50
  • 150
  • 253
  • Googling "objective-c singleton" reveals many thousands of hits. – Dave DeLong Mar 25 '11 at 22:14
  • I would name it `sharedLocationManager` instead of `instance`. Apple name them this way (except for `NSNull` and `NSUserDefaults`, but these are special). –  Mar 25 '11 at 22:16

4 Answers4

1

Basically -- yes.
Just a couple of small things:
static LocationManager *gInstance = NULL;
instead of NULL, you should use nil, it's a convention in Objective-C.

You should also overwrite alloc, new, copyWithZone:, and mutableCopyWithZone:. From Buck/Yacktman: "Cocoa Design Patterns", p. 153:

+ (id)hiddenAlloc  
{
  return [super alloc];
}

+ (id)new
{
  return [self alloc];
}

+ (id)allocWithZone:(NSZone *)zone
{
  return [[self sharedInstance] retain];
}

- (id)copyWithZone:(NSZone *)zone
{
  [self retain];
  return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
  return [self copyWithZone:zone];
}

This way, your singleton object cannot be copied. You need to call hiddenAlloc from your instance method (by the way, the method to access a Singleton object is often called sharedInstance in Objective-C).

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
goetz
  • 916
  • 6
  • 14
  • how about that CLLocationManager? – aherlambang Mar 25 '11 at 22:24
  • 1
    couple things: since `alloc` simply calls `allocWithZone:`, you don't need to override them both. `allocWithZone:` should simply return the singleton instance (retained of course) so that if you try to alloc/init a new instance, you just get the singleton back. – Dave DeLong Mar 25 '11 at 22:25
  • the one thing I am confused is with having one instance of CLLocationManager as well in this singleton class.. – aherlambang Mar 25 '11 at 22:31
0

Since the factory method "instance" is a class-level method, the @synchronized block should be @synchronized([LocationManager class]) { //}

rishabh
  • 1,155
  • 1
  • 10
  • 17
  • `self` in a class method refers to the class, so that the original code works as intended, at least in this regard. – zoul Jun 04 '12 at 18:27
  • 1
    There's already a singleton class in your code, AppDelegate class. You should ideally avoid creating a singleton, unless very explicitly required. Probably, in your case the location manager code may be simply set in AppDelegat, and the coordinates made as property in AppDelegate class. – rishabh Sep 08 '12 at 13:27
0

For other singleton styles with their pros and cons, check out this question.

Personally, I prefer this style (copied from one of the answers on that link):

static MySingleton *sharedSingleton;

+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        sharedSingleton = [[MySingleton alloc] init];
    }
}
Community
  • 1
  • 1
André Morujão
  • 6,963
  • 6
  • 31
  • 41
  • The only downside with your answer is, this will not be exactly "lazy loading". Since even if a class method for MySingleton is called, the sharedInstance object will be created immediately. – rishabh Feb 03 '13 at 07:35
  • Whether or not it is a "downside" depends on your needs. At least for the original question "lazy loading" was not stated as a requirement. – André Morujão Feb 04 '13 at 11:46
0

In fact, there's a tried-and-true method to create singletons already. Download the SynthesizeSingleton.h file (from a Cocoa with Love article). It contains a massive amount of pre-processor code which will generate any singleton for you. Hit the article for more details.

FeifanZ
  • 16,250
  • 7
  • 45
  • 84