views:

399

answers:

3

I have a Core Data based application which is built around one main entity. There are several other entities which are connected to it, one of which is an Entity called "Notes".

This Notes entity has a Date (NSDate), a Description (NSString), and one other attribute. This attribute is to have 4 possible options, of which each entity will have at least 1 and possibly all 4.

I was thinking that when a Note is being created, there could be a Segmented Controller with the 4 possible options. (Is it even possible to select multiple buttons here?)

I further want to be able to sort all of these notes by this option. That is, to create a fetch request that returns only the Notes that had Option 3 selected, for example. (Even if they also had Option 2, or even all 4 options selected.)

Any suggestions on what the best way to implement this is?

Thanks.

A: 

First, instead of trying to use one attribute to collect four possible options, I would use four separate boolean attributes. This will also allow you to filter your fetch requests very easily.

To configure each boolean, I would use a UIButton or UISwitch. The UISegmentedControl does not support multiple selection.

gerry3
A: 

Use an enumeration to define four options, e.g.:

typedef enum _NoteOptionType {
    kNoteOptionTypeOne,
    kNoteOptionTypeTwo,
    kNoteOptionTypeThree,
    kNoteOptionTypeFour,
    kNoteOptionTypes,
} NoteOptionType;

These will be numbered 0 through 5.

Core Data stores integers as NSNumber instances. You could perhaps keep an attribute in your Note entity that is called optionType, which stores the NSNumber equivalent of a NoteOptionType value.

You can convert these to NSNumber options through something like, for example, [NSNumber numberWithInt:kNoteOptionTypeOne].

You could write a convenience method to convert a NoteOptionType to a string to put into a UISegmentedControl, e.g.:

+ (NSString *) keyForNoteOptionTypeTag:(NoteOptionType)optionTypeTag {
    if (optionTypeTag == kNoteOptionTypeOne)
        return [NSString stringWithFormat:@"First"];     
    else if (optionTypeTag == kNoteOptionTypeTwo)
        return [NSString stringWithFormat:@"Second"];
    ...
    return [NSString stringWithFormat:@"Undefined"];
}

Reference it like so:

NSLog(@"second option is: %@", [Note keyForNoteOptionTypeTag:kNoteOptionTypeTwo]);

In your fetch, you can use the NSNumber values you put in your Core Data store as criteria on which to sort, through the use of an NSSortDescriptor, e.g.:

NSSortDescriptor *optionTypeDescriptor = [[NSSortDescriptor alloc] initWithKey:@"optionType" ascending:YES selector:nil];
NSArray *sortDescriptors = [NSArray arrayWithObjects:optionTypeDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[optionTypeDescriptor release];
Alex Reynolds
Since the notes can have any combination of the four possible options, for this approach you will actually need to enumerate all 24 combinations.
gerry3
A segmented control is like a radio button. There will only be one option selected from the four options.
Alex Reynolds
That said, if a different control is used, one could use a mask and `OR` the combination of various flag values, to quickly enumerate all combinations, cf. http://en.wikipedia.org/wiki/Mask_(computing)
Alex Reynolds
Actually, it looks like the segmented control is different in 3.0, so never mind. One can still use masks to generate combinations.
Alex Reynolds
A: 

To use masks for storing multiple selections, you might do something like the following:

NSInteger const kNoteOptionTypeOne = 0x1;   // 0000 0001
NSInteger const kNoteOptionTypeTwo = 0x2;   // 0000 0010
NSInteger const kNoteOptionTypeThree = 0x4; // 0000 0100
NSInteger const kNoteOptionTypeFour = 0x8;  // 0000 1000

For multiple selections, you would still store your combined mask as an NSNumber, e.g.

NSInteger mySelectionsMask = (kNoteOptionTypeOne | kNoteOptionTypeFour); // 0x0 | 0x4 = 1001 = 9
NSNumber *mySelections = [NSNumber numberWithInt:mySelectionsMask];

This mySelections value will be unique to some combination of the four options. You can go back from this combined mask to individual masks, in order to select different buttons of a segmented control, e.g.:

if ([mySelections intValue] == (kNoteOptionTypeOne | kNoteOptionTypeFour)) {
    // select buttons one and four of the segmented control
}
else if some other combination { etc. }

Or:

if (([mySelections intValue] & kNoteOptionTypeOne) == kNoteOptionTypeOne) 
    // select button one
if (([mySelections intValue] & kNoteOptionTypeTwo) == kNoteOptionTypeTwo)
    // select button two
... 

As this is stored as an NSNumber, you will be able to sort on it with an NSSortDescriptor instance as described above.

Alex Reynolds