0

I am coding a Sudoku app on Xcode, and for each cell of the game I am pairing a label and a button, one of top of the other. When the user clicks the button, the number on the label will change. I thought a NSMutableDictionary would be handy to handle each of the button/label pairs, so I created one with the button as the key and the label as the value. To test the dictionary, I printed out the value to one of the buttons, but came out as null. Here is my code:

//Within my ViewController.h file
@property (weak, nonatomic) NSMutableDictionary *dictionary;

//Within my ViewController.m file
 self.dictionary = [NSMutableDictionary dictionary];
//the (id<NSCopying>)self.A1Button is for casting purposes
[self.dictionary setObject: self.A1Label forKey: (id<NSCopying>)self.A1Button];
[self.dictionary setObject: self.A2Label forKey: (id<NSCopying>)self.A2Button];
[self.dictionary setObject: self.A3Label forKey: (id<NSCopying>)self.A3Button];
[self.dictionary setObject: self.A4Label forKey: (id<NSCopying>)self.A4Button];
[self.dictionary setObject: self.A5Label forKey: (id<NSCopying>)self.A5Button];
[self.dictionary setObject: self.A6Label forKey: (id<NSCopying>)self.A6Button];
[self.dictionary setObject: self.A7Label forKey: (id<NSCopying>)self.A7Button];
[self.dictionary setObject: self.A9Label forKey: (id<NSCopying>)self.A9Button];

NSLog(@"%@", [self.dictionary objectForKey:self.A2Button]);

What I get back is:

2015-12-28 05:44:49.940 Sudoku[6349:292670] (null)

Can anybody explain what is happening? Thanks!

rmaddy
  • 314,917
  • 42
  • 532
  • 579
FuddGubbler
  • 63
  • 1
  • 5

2 Answers2

2

if A1Button is a UIButton it does not support NSCopying protocol. Dictionary keyes are required to support it.

@property (weak, nonatomic) NSMutableDictionary *dictionary;

You must change the property to strong, of course it crashes because the method copy is not implemented in a UIButton, at the moment it doesn't because self.dictionary stays set at nil using a weak assignment.
You should revisit your logic, if you really want to use a UIButton as a key, is better to use a NSMapTable.
More info here.

Andrea
  • 26,120
  • 10
  • 85
  • 131
  • Even more correct then my answer `UIButton` does indeed not conform to `NSCopying`. `NSMapTable` will be the better solution here. – rckoenes Dec 28 '15 at 15:14
0

Got it! Instead of using a NSMutableDictionary, I used a NSMapTable to store my keys and values. A good explanation for the difference between these two data structures can be found here:

NSMapTable and NSMutableDictionary differences

In my ViewController.h file, I wrote

@property (strong,nonatomic) NSMapTable *mapTable;

to declare my NSMapTable.

Then, in my ViewController.m file, I wrote

self.mapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory
                                             valueOptions:NSMapTableWeakMemory];
[self.mapTable setObject: self.A1Label forKey:self.A1Button];
[self.mapTable setObject: self.A2Label forKey:self.A2Button];
[self.mapTable setObject: self.A3Label forKey:self.A3Button];
[self.mapTable setObject: self.A4Label forKey:self.A4Button];
[self.mapTable setObject: self.A5Label forKey:self.A5Button];
[self.mapTable setObject: self.A6Label forKey:self.A6Button];
[self.mapTable setObject: self.A7Label forKey:self.A7Button];
[self.mapTable setObject: self.A8Label forKey:self.A8Button];
[self.mapTable setObject: self.A9Label forKey:self.A9Button];

You can see that with the NSMapTable, I can specify if I want weak or strong memory. My code compiled with no errors. Thank you so much!

Community
  • 1
  • 1
FuddGubbler
  • 63
  • 1
  • 5