¿Cómo declaro propiedades de nivel de clase en Objective-C?


Tal vez esto sea obvio, pero no se como declarar propiedades de clase en Objective-C.

Necesito almacenar en caché un diccionario por clase y preguntarme cómo ponerlo en la clase.

Author: Jim Puls, 2009-03-30

10 answers

Las propiedades tienen un significado específico en Objective-C, pero creo que quieres decir algo que es equivalente a una variable estática? Por ejemplo, ¿solo una instancia para todos los tipos de Foo?

Para declarar funciones de clase en Objective-C usa el prefijo + en lugar de - para que su implementación se vea algo así como:

// Foo.h
@interface Foo {
}

+ (NSDictionary *)dictionary;

// Foo.m
+ (NSDictionary *)dictionary {
  static NSDictionary *fooDict = nil;
  if (fooDict == nil) {
    // create dict
  }
  return fooDict;
}
 183
Author: Andrew Grant,
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
2015-07-07 11:23:02

Estoy usando esta solución:

@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end

@implementation Model
static int value;
+ (int) value
{ @synchronized(self) { return value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end

Y me pareció extremadamente útil como un reemplazo del patrón Singleton.

Para usarlo, simplemente acceda a sus datos con la notación de puntos:

Model.value = 1;
NSLog(@"%d = value", Model.value);
 100
Author: spooki,
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-04-04 12:50:09

Como se ve en WWDC 2016 / XCode 8 ( qué hay de nuevo en la sesión LLVM @5:05). Las propiedades de clase se pueden declarar de la siguiente manera

@interface MyType : NSObject
@property (class) NSString *someString;
@end

NSLog(@"format string %@", MyType.someString);

Tenga en cuenta que las propiedades de clase nunca se sintetizan

@implementation
static NSString * _someString
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end
 63
Author: Alex Nolasco,
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
2017-01-10 13:56:06

Si estás buscando el equivalente a nivel de clase de @property, entonces la respuesta es "no hay tal cosa". Pero recuerde, @property es solo azúcar sintáctica, de todos modos; solo crea métodos de objeto con nombre apropiado.

Desea crear métodos de clase que accedan a variables estáticas que, como otros han dicho, solo tienen una sintaxis ligeramente diferente.

 62
Author: Jim Puls,
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
2009-03-30 05:03:15

Aquí hay una forma segura de hacerlo:

// Foo.h
@interface Foo {
}

+(NSDictionary*) dictionary;

// Foo.m
+(NSDictionary*) dictionary
{
  static NSDictionary* fooDict = nil;

  static dispatch_once_t oncePredicate;

  dispatch_once(&oncePredicate, ^{
        // create dict
    });

  return fooDict;
}

Estas ediciones aseguran que fooDict solo se cree una vez.

From Apple documentation: "dispatch_once - Ejecuta un objeto de bloque una vez y solo una vez durante la vida útil de una aplicación."

 19
Author: Quentin,
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
2015-04-24 16:44:20

A partir de Xcode 8 Objective-C ahora soporta propiedades de clase:

@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end

Dado que las propiedades de la clase nunca se sintetizan, necesita escribir su propia implementación.

@implementation MyClass
static NSUUID*_identifier = nil;

+ (NSUUID *)identifier {
  if (_identifier == nil) {
    _identifier = [[NSUUID alloc] init];
  }
  return _identifier;
}
@end

Se accede a las propiedades de la clase usando la sintaxis normal de punto en el nombre de la clase:

MyClass.identifier;
 9
Author: berbie,
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
2016-11-14 15:11:20

Las propiedades tienen valores solo en objetos, no en clases.

Si necesita almacenar algo para todos los objetos de una clase, debe usar una variable global. Puede ocultarlo declarándolo static en el archivo de implementación.

También puede considerar el uso de relaciones específicas entre sus objetos: atribuye un rol de maestro a un objeto específico de su clase y vincula otros objetos a este maestro. El maestro tendrá el diccionario como una propiedad simple. Pienso en un árbol como el utilizado para la jerarquía de vistas en aplicaciones Cocoa.

Otra opción es crear un objeto de una clase dedicada que se compone tanto de su diccionario 'clase' y un conjunto de todos los objetos relacionados con este diccionario. Esto es algo así como NSAutoreleasePool en el Cacao.

 7
Author: mouviciel,
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
2009-03-30 08:25:54

Si tiene muchas propiedades de nivel de clase, entonces un patrón singleton podría estar en orden. Algo como esto:

// Foo.h
@interface Foo

+ (Foo *)singleton;

@property 1 ...
@property 2 ...
@property 3 ...

@end

Y

// Foo.m

#import "Foo.h"

@implementation Foo

static Foo *_singleton = nil;

+ (Foo *)singleton {
    if (_singleton == nil) _singleton = [[Foo alloc] init];

    return _singleton;
}

@synthesize property1;
@synthesize property2;
@synthesise property3;

@end

Ahora acceda a sus propiedades de nivel de clase de esta manera:

[Foo singleton].property1 = value;
value = [Foo singleton].property2;
 3
Author: Pedro Borges,
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
2014-09-09 07:37:01

A partir de Xcode 8, puede usar el atributo de propiedad class como respondió Berbie.

Sin embargo, en la implementación, necesita definir tanto class getter como setter para la propiedad class usando una variable estática en lugar de un iVar.

Muestra.h

@interface Sample: NSObject
@property (class, retain) Sample *sharedSample;
@end

Muestra.m

@implementation Sample
static Sample *_sharedSample;
+ ( Sample *)sharedSample {
   if (_sharedSample==nil) {
      [Sample setSharedSample:_sharedSample];
   }
   return _sharedSample;
}

+ (void)setSharedSample:(Sample *)sample {
   _sharedSample = [[Sample alloc]init];
}
@end
 2
Author: Jean-Marie D.,
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-08-15 15:38:43

[Pruebe esta solución es simple] Puede crear una variable estática en una clase Swift y luego llamarla desde cualquier clase Objective-C.

 -3
Author: elgawady14,
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
2017-01-04 18:15:26