How to define a static table of strings in iPhone / XCode?
I want a table of state-names for debug/trace messages as I develop my custom gesture. What is wrong with this declaration and its usage?
static NSDictionary *dictStateNames = nil;
@implementation MyCustomGesture
@synthesize state;
+(void)initStateNames {
if (dictStateNames == nil) {
dictStateNames = [NSDictionary dictionaryWithObjectsAndKeys:
@"StateBegan", [NSNumber numberWithInt:UIGestureRecognizerStateBegan],
@"StateCancelled", [NSNumber numberWithInt:UIGestureRecognizerStateCancelled],
@"StateChanged", [NSNumber numberWithInt:UIGestureRecognizerStateChanged],
@"StateEnded", [NSNumber numberWithInt:UIGestureRecognizerStateEnded],
@"StateFailed", [NSNumber numberWithInt:UIGestureRecognizerStateFailed],
@"StatePossible", [NSNumber numberWithInt:UIGestureRecognizerStatePossible],
@"StateRecognized", [NSNumber numberWithInt:UIGestureRecognizerStateRecognized],
nil];
}
}
-(id) init {
self = [super init];
if (self) {
[MyCustomGesture initStateNames];
state = UIGestureRecognizerStatePossible;
}
return self;
}
-(id) initWithTarget:(id)target action:(SEL)action {
开发者_JS百科 self = [super initWithTarget:target action:action];
if (self) {
[MyCustomGesture initStateNames];
state = UIGestureRecognizerStatePossible;
}
return self;
}
+(NSString*) stateName: (UIGestureRecognizerState) state {
NSString *retName = [dictStateNames objectForKey:[NSNumber numberWithInt:state]];
if (retName == nil) {
return [NSString stringWithFormat:@"Unknown state (%@)", state];
} else {
return retName;
}
}
-(NSString*) currentStateName {
return [MyCustomGesture stateName:state];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"%s (%@): %@", __FUNCTION__, [self currentStateName], event);
}
When you store a reference to an object in a static variable, you need to ensure that it doesn't get deallocated. So you can either send it a retain
message, or create with alloc
instead of a convenience creation method. For example:
dictStateNames = [[NSDictionary dictionaryWithObjectsAndKeys:
// List of objects and keys...
nil] retain];
or this...
dictStateNames = [NSDictionary alloc] initWithObjectsAndKeys:
// List of objects and keys...
nil];
Also, you can coalesce your stateNames
getter and the initialization code into a single method, so you'll typically see Objective-C developers write a method like this:
+ (NSDictionary *)stateNames
{
static NSDictionary *stateNames;
if (stateNames == nil) {
stateNames = [NSDictionary alloc] initWithObjectsAndKeys:
// List of objects and keys...
nil];
}
return stateNames;
}
That way, there's no need to call it in an instance method (which would be wrong anyway, since a new dictionary would be created each time an instance is initialized, and unless you handled it differently, the previous one would be leaked).
On another (unrelated) note, consider rewriting your init
method as follows:
- (id)init
{
return [self initWithTarget:nil action:NULL];
}
[NSDictionary dictionaryWithObjectsAndKeys]
takes an object first followed by its key (as the method name suggests), which seems a bit backward but there it is.
精彩评论