Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to share constants (enums) between classes?

I have some UIPopoverViewControllers that do messaging to delegate UIViewControllers to pass UI events. Instead of writing a separate method for each event, I have a method in the delegate with a switch statement which determines how to handle the event based on a passed constant (example below).

This is probably poor design but it is what I've come up with. I've seen this question regarding enums or static classes but didn't understand the answers.

So..is what I am doing BAD and is there a way I can define the enums in one place so that I don't have to maintain multiple bits of code that can easily get out of sync?

EDIT Okay, digging around a bit more (here + here) I see that I might be on the right track. So I guess I need to know what and where an implementation file is in iOS.

enum {
kSetPlaybackType = 0,
kSetAllNotesOn,
kSetAllNotesOff,
kSetVelocity,
kSetDuration
};

- (void)barPropertyAction:(int)action withParam:(NSNumber *)param
{
switch (action) {
    case kSetPlaybackType:
        playbackType = [param intValue];
        if (playbackType == kPalindrome){
            palindromeDirection = kPalindromeUp;
        }
        break;

    case kSetAllNotesOn:
        for (BarNote* note in self.barNoteArray) {
            note.noteOn = YES;
        }
        [self.bar updateWindows];
        break;

    case kSetAllNotesOff:
        for (BarNote* note in self.barNoteArray) {
            note.noteOn = NO;
        }
        [self.bar updateWindows];
        break;

    case kSetVelocity:
         for (BarNote* note in self.barNoteArray) {
            note.velocity = [param intValue];
        }
        break;

    case kSetDuration:
        for (BarNote* note in self.barNoteArray) {
            note.duration = [param floatValue];
        }
        break;

    default:
        break;
}
}
like image 985
spring Avatar asked Feb 29 '12 19:02

spring


1 Answers

I'm not going to say that your approach is is that bad, but it does have a slight feel to it of the starting embryo of a "god" method - which is a method that tries to do everything. However for the number of choices you have in the code I'd say that its perfectly fine.

But sharing the enum's around is very easy. Just put them in their own .h file and import it where it is needed. You can include a .h file as one of the file types under the "C & C++" section.

The question you referenced was C# based, and one thing they did in that language was to design away the equivalent of .h files, and just use "using" statements to locate the correct symbols. In Objective-C (as in C and C++) you have to do a bit more manual work to achieve the same thing.

By the way, I would dress the enum up slightly more as:

typedef enum {
  kSetPlaybackType = 0,
  kSetAllNotesOn,
  kSetAllNotesOff,
  kSetVelocity,
  kSetDuration
} SetEnumType;

By declaring the enum in a typedef, you gain the ability to declare variables of that type. Ie instead of:

int varName = kSetAllNotesOn;

You can say:

SetEnumType varName = kSetAllNotesOn;

This gives extra hints to XCode when presenting you with autocomplete choices, and it makes it semantically better to read as a person, as you know that varName is meant to hold an enum and not just any old number.

The downside is that you might need to explicitly cast varNum between the enum type and the int type depending on what you are doing.

However I am not sure if you can declare your method signature as

- (void)barPropertyAction:(SetEnumType)action withParam:(NSNumber *)param

I am guessing you should be able to (as I think the enum is backed by an int). But if you can't, then you'd be best doing

- (void)barPropertyAction:(int)action withParam:(NSNumber *)param
{
switch ((SetEnumType)action) {
    case kSetPlaybackType:
        playbackType = [param intValue];
like image 136
Peter M Avatar answered Oct 05 '22 23:10

Peter M