0

I am creating an OS X app that will allow the user to play piano (using a MIDI keyboard). Notes will scroll from left to right and it is up to the user to play the correct note at the correct time, somewhat similar to Rock Band or any of those other games. The notes that will be scrolling will be generated from a text file or some sort of input source and it may look like this:

C4 D4 B3 A3 C4 ...

I am creating a dictionary for music notes. In music, there are 12 unique values, so let's just say that there are 12 unique letter types. The value of "C" would be 0, "C#" would be 1, "D" would be 2, etc. I need to codify them in this way because MIDI data that the user will be playing is produced numerically. "C" will always be 0, so this data needs to be hardcoded. What is the best practice for sharing this dictionary between multiple classes so that each instance of that class also has access to it?

02fentym
  • 1,762
  • 2
  • 16
  • 29
  • It would be helpful to know more about how you're planning to use this data structure in your code. A dictionary may not be your best bet here. An enum or just a set of constants might work as well / better. But it's hard to tell from the question. – wallace Dec 05 '14 at 19:50
  • Sorry for the lack of info...I'll update up top. – 02fentym Dec 05 '14 at 19:51
  • Simply share it between classes. You address an NSDictionary with a pointer, the pointer can be passed as a parameter or stored in the property of another class or fetched from a property in another class, so it's easy to give multiple classes addressability to the same object. This doesn't require any fancy initialize methods or singletons or anything, just reasonable knowledge how your application works. – Hot Licks Dec 05 '14 at 20:36
  • possible duplicate of [Passing Data between View Controllers](http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers) – Hot Licks Dec 05 '14 at 20:37
  • 1
    @HotLicks I don't think it's the same question at all. It does relate to sharing data between objects, but: a) it's not clear that the objects in question are view controllers, they could easily be model objects or views or something else; and b) the data in question is a constant dictionary used for mapping names to values, so passing the dictionary as a parameter all the time would be unnecessarily burdensome. – Caleb Dec 05 '14 at 21:26
  • @WilliamShakespeare - But a rose by any other name is still a rose. And there's not suggestion to pass the dictionary an item at a time. It's an object like any other object and it can be passed as a single object. – Hot Licks Dec 05 '14 at 21:30
  • @HotLicks Well certainly you'd pass the whole dictionary at once! I can't see how my comment suggests passing one item at a time? Anyway, I dislike singletons as much as anyone, but this is unchanging data that's necessarily the same in all cases (it's defined by MIDI). Using a class method to retrieve that data makes more sense than passing it in -- it's not changeable model data, but more like `+alphanumericCharacterSet` or `+redColor`. – Caleb Dec 05 '14 at 22:05

1 Answers1

1

What is the best practice for sharing this dictionary between multiple classes so that each instance of that class also has access to it?

Create the dictionary in the class's +initialize method and store a pointer to it in a static (file-scope) variable. +initialize is called before any instances of the class are created, so it's a good place to do whatever setup the class needs independent of specific objects.

static NSDictionary *notesDict;

@implementation SomeClass

+ (void)initialize
{
    notesDict = @{@"C" : @0, @"C#" : @1, @"D" : @2};
}

+ (NSDictionary*)notes
{
    return notesDict;
}

//...

@end

The +notes accessor makes it easy to access the dictionary from other classes, if that's necessary.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • 1
    You might also find it useful add a `+ (NSDictionary *) notesDict;` method to your class that returns this dictionary. – par Dec 05 '14 at 20:00
  • @par Agree -- I was thinking initially that the dictionary would only be used internally by a single class, but it's not clear from the question that that's true. – Caleb Dec 05 '14 at 20:30
  • Why use a dictionary when you have NS_ENUM, look an example here: http://stackoverflow.com/questions/8496903/enum-values-nsinteger-or-int, read Cœur's answer – Fantini Dec 05 '14 at 20:34
  • @Fantini That's not the same thing. OP asked for a dictionary, not an enumeration. Enumerations are great for naming related values in your code, but you can't look up values by name in an enumeration. The OP apparently has to read a stream of data containing note names and convert to note values, which is easy with a dictionary: `int note = [noteDict valueForKey:noteName];`. To do a similar mapping with an enumeration, you'd need a series of `if` statements to compare the incoming name to known names and return the appropriate value from the enum, which is slower and much less convenient. – Caleb Dec 05 '14 at 21:18
  • Yeah, using an enum would not make this better, I thought about that already. It would actually be more work, because I'd still need to match a string to an int. To me, a dictionary seems like the best solution. I need to pass the same dictionary to more than one class. I did say that in my original post. – 02fentym Dec 06 '14 at 01:50