objective c - tutorial - Solución alternativa para lograr propiedades protegidas en Objective-C
objective c vs swift (4)
Claro, eso funciona bien. Apple usa el mismo enfoque, por ejemplo, en la clase UIGestureRecognizer
. Las subclases deben importar el archivo UIGestureRecognizerSubclass.h
adicional y anular los métodos que se declaran en ese archivo.
He estado intentando encontrar una solución alternativa para declarar propiedades @protected en Objective-C, de modo que solo las subclases de la jerarquía puedan acceder a ellas (solo lectura, no escritura). Leí que no hay una forma documentada de hacerlo así que pensé en esta solución alternativa y quería preguntarle 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 siempre:
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. Decidí una segunda interfaz llamada ClassA_protected.h que realmente funciona como una extensión de ClassA.h y nos permite etiquetar la propiedad como de 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 ClassA.h , importará ClassA_protected.h en su lugar. Entonces, un niño como, por ejemplo, ClassB.h , sería el siguiente:
#import "ClassA_protected.h"
@interface ClassB : ClassA
@end
Y un ejemplo de acceso a esta propiedad desde la implementación de ClassB.m :
@implementation ClassB
-(void) method {
//edit protected variable
_myProtectedInt= 1;
//normal access
self.muProtectedInt;
}
@end
Importe el encabezado protegido solo en la implementación. p.ej
ClassB.h
#import "ClassA.h"
@interface ClassB : ClassA
@end
ClassB.m
#import "ClassA_protected.h"
@implementation ClassB
@end
Y en un marco, el encabezado protegido debe marcarse como proyecto para que no se incluya en los encabezados públicos del marco. Apple generalmente usa el sufijo _Internal.h para sus métodos protegidos.
Para iniciar o anular una propiedad de carga con carga lenta, necesitaría acceso directo al @ivar protegido, sin embargo, para su uso, sería mejor volver a declarar la propiedad como readwrite, entonces puede aprovechar cualquier característica del setter, atomicity por ejemplo .
Para simples "propiedades" 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.
Si pides opinión, esta es mía: si decides mutar tu
_myProtectedInt
probablemente lo logre de todos modos, porque definitivamente es posible con Objective-C runtime. Excepto esto, tu solución está bastante bien.