-2

I have the following method (it is an instance method of ShoppingCart):

- (void) showShoppingCartProducts
 {
   for (Product *eachProduct in products)
    {
      [eachProduct logName]
    }
}

I have another method (it is an instance method of ShoppingCart):

- (void) addProduct: (Product *) newProduct {
    [products objectForKey: newProduct.name];
}

It is supposed to iterate through each (Product *) eachProduct in (NSMutableDictionary *) products.

logName does the following (it is an instance method of Product):

- (void) logName
{
  NSLog(@"%@", self.name);
}

Here is my main() function

int main(int argc, const char * argv[]) {

    ShoppingCart* myShoppingCart = [[ShoppingCart alloc] init];

    Product* myProduct = [[Product alloc] init];

    myProduct.name = @"My Latest Product";

    [myShoppingCart addProduct: myProduct];

    [myShoppingCart showShoppingCartProducts];

    return 0;
}

After running the program, it returns 0, but displays nothing.

Is it possible to use fast enumeration on a NSMutableDictionary?

Fine Man
  • 455
  • 4
  • 17

1 Answers1

2

This:

NOTE: [myShoppingCart addProduct: myProduct] just adds (Product ) myProduct to a NSMutableDictionary products in (ShoppingCart *) myShoppingCart

is not adequate explanation. There's no such thing as "just adding an object to an NSMutableDictionary". You set a value for a key in dictionaries. Which is myProduct, the value or the key? If it's the value, what is the key? If it's the key, what is the value?

To answer the basic question: yes, you can fast enumerate over a dictionary. The keys are enumerated. If you want the value for each key, you then have to look that up using -objectForKey: or the subscripting syntax.

If you think you're adding an object to a dictionary (or any other collection) but then the dictionary (collection) seems to be empty, that's probably because you're dealing with a nil pointer and not an actual collection. You neglected to create the collection and store a strong reference to it.


You've edited the question to show this method:

- (void) addProduct: (Product *) newProduct {
    [products objectForKey: newProduct.name];
}

That method does not add the product to the dictionary. -objectForKey: looks up an object that may already be in the dictionary by its key. It doesn't modify the dictionary. You probably meant to do this:

- (void) addProduct: (Product *) newProduct {
    [products setObject:newProduct forKey:newProduct.name];
}

Given that you succeed in adding Product instances to the dictionary and the name is an NSString*, your enumeration should look like this:

for (NSString* name in products)
{
    Product* product = [products objectForKey:name];
    [product logName]
}
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Sorry, I fixed the error. The value I want to log is the '@property NSString *name' of the 'Products' class instances (in this example, I have one: myProduct) – Fine Man Sep 22 '14 at 01:06
  • So, there was no problem with the NSMutableDictionary, and was just the wrong method? Still, when I use the correct method (that you have given me), the result is the same. – Fine Man Sep 22 '14 at 01:20
  • Are you sure the `products` instance variable (I'm assuming it's an instance variable) is not `nil`? Try logging it. Also, show where it is set. That should probably be within the implementation of `-[ShoppingCart init]`. – Ken Thomases Sep 22 '14 at 01:40
  • That's a good point. Does @property do that for me as a setter/getter method, or do I have to override it myself? If so, how? – Fine Man Sep 22 '14 at 01:47
  • `@property` declares a property, which usually amounts to declaring (but not defining) accessor methods. `@synthesize`, which can be implicit with modern compilers, can generate (define) the accessor methods and can even generate the instance variable for you (although it would typically have an underscore, such as `_products`; you wouldn't be able to just refer to it as `products`). However, the variable is just a holder for a pointer to an object. It doesn't create the object itself. You need to do that. For example, `_products = [[NSMutableDictionary alloc] init];` in `-init`. – Ken Thomases Sep 22 '14 at 01:58
  • I suppose you mean the '-init' of ShoppingCart? When I do type in the line you provided, Xcode complains that it should be 'products' rather than '_products'. When I fix the complaint, I end up with 'Thread 1: signal SIGABRT' mark, causing the program to terminate. – Fine Man Sep 22 '14 at 02:37
  • Most likely the fast enumeration is now working and has allowed execution to continue to a different error. For example, the keys of your dictionary are product names, which I assume is a string. However, in your `for` loop, you a) declare the loop variable as a `Product*` which it isn't, and b) call `-logName` on it, which is not a method on an `NSString`. As I said above, fast enumeration on a dictionary enumerates the keys. If you then want the value for a given key, you need to look it up. – Ken Thomases Sep 22 '14 at 02:58