Confusion regarding how to use a NSMutableArray and Singleton

171 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
RobP 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
MuhammadTalhaSiddiqui 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
Thorsten 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];