œil - Quel est le mécanisme sous-jacent de la synthèse d'ivar dans l'environnement d'exécution Objective C moderne?




ubbe ragnarsson (2)

L'une des fonctionnalités de l'environnement d'exécution Objective C moderne (64 bits OS X et iPhone OS) est la possibilité pour les propriétés de synthétiser dynamiquement des ivars sans les déclarer explicitement dans la classe:

@interface MyClass : NSObject {
//  NSString *name; unnecessary on modern runtimes
}

@property (retain) NSStrng *name;

@end

@implementation MyClass

@synthesize name;

@end

Dans une grande partie de mon code, j'utilise des implémentations de getter personnalisées pour initialiser les propriétés:

- (NSString *) name {
  if (!name) {
    name = @"Louis";
  }

  return name;
}

Ce qui précède est incompatible avec les ivars synthétisés car il doit accéder à un ivar qui n'est pas déclaré dans l'en-tête. Pour diverses raisons, je voudrais mettre à jour un certain nombre de mes cadres personnels pour utiliser des ivars synthétisés lorsqu'ils sont construits sur les runtimes modernes, le code ci-dessus doit être modifié pour fonctionner avec des ivars synthétisés afin d'atteindre cet objectif.

Tandis que la documentation d'Objective C 2.0 indique que les accesseurs synthétisés sur l'exécution moderne synthétiseront l'ivar lors de la première utilisation. Il ne précise pas quel mécanisme de bas niveau est utilisé pour cela. Est-ce fait par class_getInstanceVariable (), les restrictions sur class_addIvar () sont-elles relâchées, est-ce une fonction non documentée dans l'exécution de l'objectif C 2.0? Bien que je puisse implémenter mon propre stockage secondaire pour les données supportant mes propriétés, je préfère utiliser le mécanisme que les accesseurs synthétisés utilisent.


Je suis allé voir la documentation à nouveau tout à l'heure, et je pense que vous la lisez mal. Les ivars synthétisés sont créés au moment de la compilation, pas au moment de l'exécution.

Selon la documentation Objective-C 2.0 :

Il y a des différences dans le comportement qui dépendent de l'exécution (voir aussi "Différences d'exécution"):

Pour les runtimes hérités, les variables d'instance doivent déjà être déclarées dans le bloc @interface. Si une variable d'instance du même nom et du même type que la propriété existe, elle est utilisée. Dans le cas contraire, vous obtenez une erreur de compilation.

Pour les temps d'exécution modernes, les variables d'instance sont synthétisées selon les besoins. Si une variable d'instance du même nom existe déjà, elle est utilisée.

Il vous suffit donc de déclarer la variable d'instance dont vous avez besoin, et le même code fonctionnera sur les deux runtimes ...


Vous ajoutez des propriétés à l'exécution avec le protocole NSKeyValueCoding .

[myObject setValue:@"whatever" forKey:@"foo"];