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
Author: Binarian, 2012-06-15

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.

 20
Author: Ole Begemann,
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.

 7
Author: Septiadi Agus,
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.

 3
Author: Oleg Trakhman,
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.

 0
Author: malhal,
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