Why do we need pointers 2x on "item"?


#1

In BNRItemStore I see two pointers to item. Is this done for sake of ARC, working under the assumption the reference gets dropped after createItem method is called and needs to be created again when removeItem is called?

[code]- (BNRItem *) createItem
{
BNRItem *item = [BNRItem randomItem];
[self.privateItems addObject:item];
return item;
}

  • (void)removeItem:(BNRItem *)item;
    {
    [self.privateItems removeObjectIdenticalTo:item];
    }
    [/code]

#2

I’m not sure I’m going to answer your question correctly, because I have a feeling I’m not understanding you fully. So please ask questions if I didn’t understand, but let me give it a shot.

When you call the +randomItem method, a new BNRItem is created on the heap and we have one pointer to this BNRItem, which is the item local variable. At this point, the BNRItem has one owner.

On the next line of code, we add that BNRItem to the privateItems array. Since arrays own their objects, the BNRItem now has two owners: one from the item local variable and another from the privateItems array.

The thing to remember is, item is a local variable, so when we return from the createItem method, the local variable goes out of scope, and so one owner to the BNRItem is lost. At this point, the only reference we have to the BNRItem is through the privateItems array.

We aren’t recreating anything in the removeItem: method. A pointer to some item (aka a memory address) is passed in, and the privateItems array removed the BNRItem with the same memory address from itself. As mentioned in the previous paragraph, since the privateItems array is the only object that is an owner on the BNRItem, when it is removed from the array, its ownership count decrements from 1 to 0, and so the BNRItem will get destroyed.

Let me know if that helps.


#3

Awesome! I think it’s clear now. Thank you!


#4

Another point of clarification is that the choice of the name item in both methods is logical, but completely arbitrary. We could have written the second method as:

- (void)removeItem:(BNRItem *)foobar
{
    [self.privateItems removeObjectIdenticalTo:foobar];
}

and everything would still be the same.


#5

Just remember about Scoping, the BNRItem *item is local for each method, so you just can pass a value in some of them. So, you can work as you wish with them.