ios - static NSDictionary*const letterValues = @{...} en un método no compila
objective-c (3)
Puede usar estática, pero la asignación no se puede hacer en la misma línea. Prueba esto:
- (void)awakeFromNib {
[super awakeFromNib];
static NSDictionary* letterValues = nil;
if (!letterValues) {
letterValues = @{@"A": @1,
@"B": @4,
@"C": @4,
// ...
@"X": @8,
@"Y": @3,
@"Z": @10};
}
...
}
La razón es que la sintaxis @{<key> : <value>}
es traducida por el compilador a un método Objective-C ( [[NSPlaceholderDictionary alloc] initWithObjects:forKeys:count:]
), que no se puede resolver en tiempo de compilación .
En un juego de palabras para iPhone :
Estoy tratando de usar el siguiente código en mi vista personalizada Tile.m :
- (void)awakeFromNib
{
[super awakeFromNib];
static NSDictionary* const letterValues = @{
@"A": @1,
@"B": @4,
@"C": @4,
// ...
@"X": @8,
@"Y": @3,
@"Z": @10,
};
NSString* randomLetter = [kLetters substringWithRange:[kLetters rangeOfComposedCharacterSequenceAtIndex:arc4random_uniform(kLetters.length)]];
int letterValue = [letterValues[randomLetter] integerValue];
_smallLetter.text = _bigLetter.text = randomLetter;
_smallValue.text = _bigValue.text = [NSString stringWithFormat:@"%d", letterValue];
}
Desafortunadamente, esto me da error de compilación. El elemento inicializador no es una constante en tiempo de compilación y tengo que eliminar la palabra clave static
para que mi aplicación se compile en Xcode (aquí a pantalla completa ):
Creo que inicializo el NSDictionary
correctamente, utilizando la nueva sintaxis de Objective-C Literals .
Pero ¿por qué no puedo usar static
aquí?
¿Pensé que sería apropiado aquí para asegurarme de que mi Constante letterValues
se establece solo una vez?
Solo puede establecer una variable estática durante la inicialización con una constante. @ {} crea un objeto, por lo tanto no una constante.
Haz esto en su lugar:
- (void)awakeFromNib
{
[super awakeFromNib];
static NSDictionary* letterValues = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
letterValues = @{
@"A": @1,
@"B": @4,
@"C": @4,
// ...
@"X": @8,
@"Y": @3,
@"Z": @10,
};
});
...
}
Algunas otras respuestas aquí sugieren una comprobación de nil en lugar de despachar una vez, pero eso puede causar problemas al crear varias teselas al mismo tiempo (a través de subprocesos). dispatch_once implementa el bloqueo requerido.
NSDictionary
objetos NSDictionary
no se pueden crear en tiempo de compilación. Sin embargo, si necesita un objeto estático, puede crear uno. Puede, por ejemplo, usar el método de initialize
, como este:
static NSDictionary* letterValues;
+ (void)initialize
{
if (self == [MyClass class]) {
letterValues = @{
@"A": @1,
@"B": @4,
@"C": @4,
@"X": @8,
@"Y": @3,
@"Z": @10,
};
}
}
La instrucción if está ahí para evitar múltiples llamadas de tu código en las subclases de MyClass
.