0
votes

First question: Basically I'm attempting to add NSMutableDictionary objects to an NSMutableArray by using a method addItem.

-(void)addItem:(id)ObID name:(id)ObName description:(id)ObDesc menuName:(id)ObmName menuID:(id)ObmID mid:(id)Obmid pod:(id)pod type:(id)obType price:(id)price
{
    NSMutableDictionary *itemToAdd = [[NSMutableDictionary alloc]init];
    [itemToAdd setValue:ObID forKey:@"id"];
    [itemToAdd setValue:ObName forKey:@"name"];
    [itemToAdd setValue:ObDesc forKey:@"description"];
    [itemToAdd setValue:ObmName forKey:@"mname"];
    [itemToAdd setValue:ObmID forKey:@"menu_id"];
    [itemToAdd setValue:Obmid forKey:@"mid"];
    [itemToAdd setValue:pod forKey:@"POD"];
    [itemToAdd setValue:obType forKey:@"Type"];
    [itemToAdd setValue:price forKey:@"Price"];
    [itemToAdd setValue:@"1" forKey:@"Amount"];

    [items addObject:itemToAdd];
}

However when this method is called again later the next object that is added to the overwrites the value of an object with the same keys. Im aware this is because an array simply retains a memory address, hence when the same object simply with a different type "obType" is added all of those values change.

How am I able to add objects to an NSMutableArray without them referencing each other?

Example:

Output after adding one object:

        {
    Amount = 1;
    POD = BOTH;
    Type =         {
        0 = Vegetarian;
        1 = Aussie;
    };
    description = "Online Special Only - Two Large Pizza's $25 (No half halves or extra toppings!) Enjoy!";
    id = 7596;
    "menu_id" = 112;
    mid = 112;
    mname = "Deal";
    name = "Hungry? Two Large Pizzas!";
}

)

Output after adding another object of same ID however of a different type:

    {
    Amount = 1;
    POD = BOTH;
    Type =         {
        0 = "Plain";
        1 = Aussie;
    };
    description = "Online Special Only - Two Large Pizza's $25 (No half halves or extra toppings!) Enjoy!";
    id = 7596;
    "menu_id" = 112;
    mid = 112;
    mname = "Deal";
    name = "Two Large Pizzas!";
},
    {
    Amount = 1;
    POD = BOTH;
    Type =         {
        0 = "Plain";
        1 = Aussie;
    };
    description = "Online Special Only - Two Large Pizza's $25 (No half halves or extra toppings!) Enjoy!";
    id = 7555;
    "menu_id" = 112;
    mid = 112;
    mname = "Deal";
    name = Two Large Pizzas!";
}

)

As can be seen both object types have changed.

Ok so I solved the problem, not 100% sure why. I was passing in the type object as an NSMutableDictionary which if an item had 2 variations, one object in the dictionary would have a key of 0 the other 1 when passed in like this they overwrite each other. Passing just the values in as an NSArray fixes this.

Done by passing in:

NSArray * values = [selectedItemOptions allValues];

Thanks all who helped.

1
I suggest logging the count value of items at the start of this method to actually confirm that the previous object is still there. Also it may be useful to see how and where items is declared and initialised. - Bamsworld

1 Answers

0
votes

I can't give you the answer, there is not enough information provided to do that, but maybe I can help you figure it out yourself. You write:

Im aware this is because an array simply retains a memory address, hence when the same object simply with a different type "obType" is added all of those values change.

That is not what happens in your code, though there are situations where what is in an array may appear to change - and that is what you are probably seeing. The line:

NSMutableDictionary *itemToAdd = [[NSMutableDictionary alloc]init];

generates a new, never before seen, mutable dictionary. You can log the address (effectively the identity(1)) of this object by adding:

NSLog(@"Created itemToAdd: %p", itemToAdd);

after the above line. The %p format will produce the address of the newly created object, and every object has a unique address. When you then get to the line:

[items addObject:itemToAdd];

The new dictionary is added to whichever array is referenced by items - and that is very important. Any variable, such as items and itemToAdd, references an object, it is not the object itself. So the array being referenced by items could change between calls to addItem:. You should check this and you can do that by adding(2):

NSLog(@"addItem called, items = %p containing %ld element", items, items.count);
for(id someThing in items)
   NSLog(@"    element: %p", someThing);

to the start of your method. This will first tell you the address of the array currently referenced by items and how many items that array contains. The for loop will then output the address of each element of the array (if there are any).

Further note that addObject: will always add an item to the array, it doesn't matter if the same item is already in the array - add it twice and the array appears to have two elements, both of which reference the same item. When the above code displays the count it should be increasing unless you are removing elements from the array somewhere.

Add those statements and look at the results. Among the possibilities that would produce the results you are reporting:

  • The array referenced by items is changing
  • The dictionary you add is being removed
  • Etc.

HTH


(1) Addresses can be reused, after an object is no longer required and destroyed by ARC its memory may be reused for a new object. So the address does not strictly identify a unique object, you just need to be aware of this

(2) I am assuming 64-bit here, if not you need to change the %ld format or add a cast.