Solución para lograr propiedades protegidas en Objective-C
He estado tratando de encontrar una solución para declarar propiedades @protected en Objective-C para que solo las subclases de la jerarquía puedan acceder a ellas (solo lectura, no escritura). Leí que no hay una forma documentada de hacer esto, así que pensé en esta solución y quería preguntar la opinión de StackOverflow al respecto.
Cada clase personalizada en la parte superior de la jerarquía contiene tres clases, una implementación y dos interfaces. Vamos a nombrarlos:
ClassA.h
ClassA_protected.h
ClassA.m
Entonces cualquier subclase de esta ClassA sería como de costumbre:
ClassB.h
ClassB.m
Primero creé la interfaz ClassA.h donde declaro una variable int protegida para que cualquier subclase de ClassA pueda tener acceso a ella:
@interface ClassA : NSObject{
@protected
int _myProtectedInt;
}
@end
El siguiente paso es la solución de la que estaba hablando. Sin embargo, una vez que lo lea verá que es bastante sencillo. Declaré una segunda interfaz llamada ClassA_protected.h que en realidad funciona como una extensión de ClassA.h y nos permite etiquetar la propiedad como readonly
:
#import "ClassA.h"
@interface ClassA ()
@property (nonatomic , readonly) int myProtectedInt;
@end
El último paso para preparar la jerarquía protegida es declarar su implementación en ClassA.m donde solo sintetizamos nuestra propiedad:
#import "ClassA_protected.h"
@implementation ClassA
@synthesize myProtectedInt = _ myProtectedInt;
@end
De esta manera, cada clase que necesita ser una subclase de Clase.h , importará ClassA_protected.h en su lugar. Así que un niño como, por ejemplo ClassB.h, sería como sigue:
#import "ClassA_protected.h"
@interface ClassB : ClassA
@end
Y un ejemplo de acceso a esta propiedad desde ClassB.m aplicación:
@implementation ClassB
-(void) method {
//edit protected variable
_myProtectedInt= 1;
//normal access
self.muProtectedInt;
}
@end
4 answers
Claro, eso funciona bien. Apple utiliza el mismo enfoque, por ejemplo, en la clase UIGestureRecognizer
. Las subclases tienen que importar el archivo adicional UIGestureRecognizerSubclass.h
y sobrescribir los métodos que se declaran en ese archivo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-15 09:05:59
Para "propiedades" simples solo use ivar en su lugar. Eso es tan bueno como las propiedades para todos los propósitos prácticos.
Además, el valor predeterminado ya está protegido.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-10 08:00:26
Si pides opinión, esta es la mía: Si uno decide mutar tu
_myProtectedInt
Probablemente tendrá éxito de todos modos, porque es definitivamente posible con Objective-C runtime. Excepto esto, su solución está bastante bien.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-15 09:12:12
Importe el encabezado protegido solo en la implementación. por ejemplo,
Clase B.h
#import "ClassA.h"
@interface ClassB : ClassA
@end
Clase B.m
#import "ClassA_protected.h"
@implementation ClassB
@end
Y en un framework la cabecera protegida debe marcarse como proyecto para que no esté incluida en las cabeceras públicas del framework. Apple suele utilizar el sufijo _Internal.h por sus métodos protegidos.
Para iniciar o anular una propiedad get lazy loaded, necesitaría acceso directo al ivar @protected, sin embargo, para su uso sería mejor volver a declarar la propiedad como readwrite en lugar entonces usted puede tomar ventaja de cualquier característica del setter, atomicity por ejemplo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-08 10:30:06