0

I am experimenting using a singleton for the first time. I would like to have an array that is global to all my view controllers with some special methods to add and remove items (this is for a shopping cart kind of thing).

My singleton class is called Cart.

This is Cart.h:

@interface Cart : NSObject  
@property NSMutableArray *cartArray;

+ (Cart *)sharedManager;    // Class method to return the singleton object

- (void)addItemToCart:(id)object;
- (void)removeItemFromCart:(id)object;
- (void)emptyAllItemsFromCart:(id)object;
- (NSMutableArray *)returnArray;

@end

This is Cart.m:

@implementation Cart

// @property NSMutableArray *cartArray;

NSMutableArray *cartArray;

+ (Cart *)sharedManager
{
    Cart *cartObject = [[Cart alloc]init];
//    self.cartArray = [NSMutableArray new];
    return cartObject;

}

- (void)addItemToCart:(id)object
{
    if(!cartArray){

        cartArray = [NSMutableArray new];
    }

    [cartArray addObject:object];

}
- (void)removeItemFromCart:(id)object
{
    [cartArray removeObject:object];
}
- (void)emptyAllItemsFromCart:(id)object
{
    [cartArray removeAllObjects];
}

Then in one of my view controllers, I am trying to pass a custom object (that contains strings and NSNumbers) to my global array.

//    Cart *singleton = [Cart sharedManager];
//    [singleton addItemToCart:self.localChosenAccessory];

Or maybe something like:

Cart *mySingleton = [Cart sharedManager];
mySingleton.cartArray = self.addToCartArray;

Both above singleton objects come out to nil.

I'm new to singletons and Objective C in general. I would appreciate any advice. I have read through a lot of similar Stack Overflow links but don't quite get it in my situation.

May Yang
  • 523
  • 1
  • 5
  • 18

3 Answers3

0

In your [Cart sharedManager] method you are creating a new instance every time no matter what. That's not a singleton! You want something like this:

static Cart *managerInstance;
+ (Cart *)sharedManager
{
    if(!managerInstance) {
        managerInstance = [[Cart alloc] init];
        // put code in instance init if you need to initialize array
    }
    return managerInstance;

}

Then you can call sharedManager as many times as you want and always get to the same singleton instance.

RobP
  • 9,144
  • 3
  • 20
  • 33
  • Thank you, this seems like it is partially working (I can see my objects in my array when I put breakpoints in my Singleton class). But can you give me an example of how to call my singleton array when I am in another view controller? – May Yang Dec 06 '14 at 21:36
  • From pretty much anywhere, you can access your methods, either inline like `NSMutableArray *cartArray = [[Cart sharedManager] returnArray]` or if you are doing several operations, like: `Cart *theCart = [Cart sharedManager]; NSMutableArray *cartArray = [theCart return Array];` – RobP Dec 07 '14 at 05:40
  • Thank you, I was able to figure it out and my singleton is working great. – May Yang Dec 07 '14 at 21:16
  • Awesome. I'd be grateful if you'd accept/upvote this answer ;) – RobP Dec 08 '14 at 16:51
  • I believe the original asker can always accept an answer though, right? – RobP Dec 08 '14 at 18:50
  • Thanks - didn't know I could do that. just selected. – May Yang Dec 08 '14 at 22:19
0

You are initializing your object every time you ask shared manager to get you the instance of singleton class. Replace this with your shared manager and then try it out:

static Cart *cartObject = nil;
+ (id)sharedManager {
    if (cartObject == nil)
        cartObject = [[self alloc] init];
    return cartObject;
  }
  • you never declared this cartObject that you refer to... also, it's a style thing but I think it leads to problems to omit the { } brackets around 'if' blocks. Inevitably you intend to add a line later and it does the wrong thing. – RobP Dec 06 '14 at 08:22
  • we can't decalre an object into sharedManager function, if we does this so it will always be called whenever we want to access the instance of this class. We should do this inside the scope of class but not in sharedManager. – MuhammadTalhaSiddiqui Dec 06 '14 at 08:28
  • 1
    right, you should show that declaration to make your example complete. – RobP Dec 06 '14 at 08:30
0

Don't forget to save the created object:

@implementation Cart

static Cart *sharedInstance = nil;

+ (Cart *)sharedInstance {
    static dispatch_once_t pred;        // Lock
    dispatch_once(&pred, ^{             // This code is called at most once per app
        sharedInstance = [[Cart alloc] init];
    });

    return sharedInstance;
}

...

and then you can call it like this:

Cart *mySingleton = [Cart sharedInstance];
[mySingleton addItemToCart:someObject];
Thorsten
  • 3,102
  • 14
  • 14