I run into design choices like this often and struggle a bit; I'm looking for some other perspectives.
I often want to keep lists of, or pass around chunks of state that are basically just sets of values. The values tend to be primitive types: floats, NSTimeIntervals, CGPoints, etc.
My first inclination is often to create C structures for these sets of properties, e.g.
typedef struct _STATE {
float foo;
NSTimeInterval elapsed;
CGPoint point;
} STATE;
etc.
But C structures don't play nicely with the native Cocoa collection classes (NSArray
, NSSet
, NSDictionary
), and using overmany of them to track lots of state feels like it runs against the grain of rest of my Cocoa-friendly code-- I end up having and directly managing arrays of structs, and passing struct pointers around in messages, etc.
On the other hand, since raw performance isn't necessarily critical, I could encode these values into a NSDictionary, wrapping them all in NSValue
or NSNumber
, but the resulting syntax is hardly terse, and a little fragile, requiring type and name correctness at runtime for both the insert and the lookup:
[stateDict setObject:[NSNumber numberWithFloat:foo] forKey:@"bar"];
...
float something = [[stateDict objectForKey:@"bar"] floatValue];
and some types, like NSTimeInterval, are only able to be used with some (arguable) hackery (typecast to double in that case).
Finally, I could create data-only container objects, with private member data and only getters/setters. (These would be called "beans" in Java.) These are more terse to access than dictionaries, more Cocoa than structs, but feel like overkill to me, especially if I only need them as "inner classes" that are used for state management internal to a single object type.
How do you, great Cocoa programming public, do this?
Depending on the situation, I run either with using NSDictionary classes for arbitrary data, or I create container classes (the @property/synthesize tags in Objective C make this really easy). By using ObjC for the header file:
@interface StateObject : NSObject {
NSNumber *foo;
NSTimeInterval *elapsed;
CGPoint point;
}
@property (retain) NSNumber *foo;
@property (retain) NSTimeInterval *elapsed;
@property (copy) CGPoint point;
@end
One can then use @synthesize <variable>
in the .m file to automatically create the setters/getters. Then, while anonymous NSNumbers are still ornery, you can do:
myStateObject.foo = [NSNumber numberWithFloat:7.0];
This should take most of the pain away, and let you use the Cocoa collection classes to better shuffle data around.