Confusion regarding how to use a NSMutableArray and Singleton

167 Views Asked by At

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.

3

There are 3 best solutions below

6
On BEST ANSWER

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.

3
On

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;
  }
0
On

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];