objective-c - sistema - swift versions
Si una subclase se refiere a una superclase ivar, falla la sÃntesis de una propiedad no relacionada (3)
Editar: Me acabo de dar cuenta de que esta otra pregunta de Desbordamiento de pila pregunta de forma muy similar: ¿Por qué una subclase @propiedad sin ivar correspondiente ivar oculta superclases ivars?
Este es un comportamiento interesante que no puedo encontrar documentado en nada oficial o no oficial (blog, tweet, pregunta SO, etc.). Lo reduje a su esencia y lo probé en un nuevo proyecto de Xcode, pero no puedo explicarlo.
MyBaseClass tiene una variable de instancia:
@interface MyBaseClass : NSObject {
NSObject *fooInstanceVar;
}
@end
MySubclass extiende MyBaseClass y declara una propiedad totalmente no relacionada (es decir, la propiedad no está diseñada para ser respaldada por la variable de instancia):
#import "MyBaseClass.h"
@interface MySubclass : MyBaseClass { }
@property (nonatomic, retain) NSObject *barProperty;
@end
Si la implementación de MySubclass no sintetiza la propiedad sino que implementa los métodos de acceso, todo está bien (sin error del compilador):
#import "MySubclass.h"
@implementation MySubclass
- (NSObject*)barProperty {
return [[NSObject alloc] init]; // pls ignore flagrant violation of memory rules.
}
- (void)setBarProperty:(NSObject *)obj { /* no-op */ }
- (void)doSomethingWithProperty {
NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
NSLog(@"%@", array);
}
@end
Pero si elimino los métodos de acceso a la propiedad y los reemplazo con una declaración de synthesize
para la propiedad, obtengo un error del compilador: ''fooInstanceVar'' undeclared (first use in this function)
.
#import "MySubclass.h"
@implementation MySubclass
@synthesize barProperty;
- (void)doSomethingWithProperty {
NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
NSLog(@"%@", array);
}
@end
Este error desaparece si fooInstanceVar
la declaración de synthesize
, o si no hago referencia a la variable de instancia fooInstanceVar
desde MySubclass.m, o si pongo todas las definiciones de interfaz e implementación en un único archivo. Este error también parece ocurrir tanto en la configuración de compilación de GCC 4.2 como de GCC / LLVM.
¿Alguien puede explicar lo que está pasando aquí?
El compilador se está comportando correctamente; la síntesis en una subclase que usa almacenamiento en una superclase está prohibida.
Hubo un error al respecto en contra de llvm en algún momento. Puede estar en la base de datos de errores de acceso público.
En cualquier caso, presente un error que solicite una aclaración de esta regla en particular.
Acabo de probar esto y compila sin previo aviso. ¿Qué no estoy haciendo?
@interface MyBaseClass : NSObject {
NSObject *fooInstanceVar;
}
@end
@interface MySubclass : MyBaseClass { }
@property (nonatomic, retain) NSObject *barProperty;
@end
@implementation MyBaseClass
@end
@implementation MySubclass
@synthesize barProperty;
- (void)doSomethingWithProperty {
NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
NSLog(@"%@", array);
}
@end
No está claro qué problema estás tratando de resolver. Todas las variables de instancia no son frágiles en todas partes, excepto Mac OS X de 32 bits.
No puedo reproducir tu error tampoco. ¿Tiene un indicador de compilador no predeterminado establecido? ¿Podría proporcionar una copia de su proyecto? Definitivamente parece ser un error en el compilador.
Consulte este artículo aquí para obtener el mejor uso de @ property / @ synthesize. Un resumen rápido es eliminar todos tus ivars de tus objetos (a menos que necesites usar el tiempo de ejecución de 32 bits por algún motivo). Entonces solo use sus getters y setters, en lugar de acceder directamente a los ivars sintetizados. Siguiendo esto evitará cualquier problema futuro con este error.
Como se respondió en esta pregunta: objetivo c xcode 4.0.2: la subclase no puede acceder a las variables de la superclase "no se declaró en este ámbito"
Del documento: Apple Objective-C Programming Langage: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163- CH12-TPXREF125
Se puede acceder a la variable de instancia dentro de la clase que la declara y dentro de las clases que la heredan. Todas las variables de instancia sin una directiva de alcance explícito tienen @protected scope.
Sin embargo, se puede acceder a una variable de instancia pública en cualquier lugar como si fuera un campo en una estructura C. Por ejemplo:
Trabajador * ceo = [[Worker alloc] init];
ceo-> boss = nil;
Tengo el error de compilación usando LLVM GCC 4.2 (para un proyecto de iOS, en el dispositivo):
error: ''fooInstanceVar'' no declarado (primer uso en esta función) y el mismo usando GCC 4.2: error: ''fooInstanceVar'' no declarado (primer uso en esta función)
Puedo compilar usando LLVM Compiler 2.0 sin error.
Para compilar con LLVM GCC 4.2 y GCC 4.2 con el uso de self->:
[NSArray arrayWithObjects: self.barProperty, self-> fooInstanceVar, nil]; en el método doSomethingWithProperty.