J'ai un film de classe, chacun d'entre eux stockant un identifiant unique. En C #, Java etc.), je peux définir un ID statique actuel et chaque fois que je le définis, je peux augmenter le ID actuel et la modification se produit au niveau de la classe et non au niveau de l'objet. Peut-on le faire dans Objective-C? J'ai eu beaucoup de difficulté à trouver une réponse à cette question.
Description du problème :
Une alternative :
Simuler un comportement de variable de classe à l'aide des fonctionnalités d'Objective-C
Declare/Define une variable statique dans classA.m afin qu'elle ne soit accessible que pour les méthodes classA (et tout ce que vous mettez dans classA.m).
Remplacez la méthode de classe d'initialisation NSObject pour initialiser une seule fois la variable statique avec une instance de ClassB.
Vous vous demanderez pourquoi je devrais écraser la méthode d'initialisation de NSObject. Apple sur cette méthode a pour réponse: "Le runtime envoie l'initialisation à chaque classe d'un programme exactement une fois juste avant la classe, ou toute classe qui en hérite, reçoit son premier message. depuis le programme. (Ainsi, la méthode ne peut jamais être invoquée si la classe n’est pas utilisée.) ".
N'hésitez pas à utiliser la variable statique dans n'importe quelle méthode de classe/instance de ClassA.
Exemple de code :
fichier: classA.m
static ClassB *classVariableName = nil;
@implementation ClassA
...
+(void) initialize
{
if (! classVariableName)
classVariableName = [[ClassB alloc] init];
}
+(void) classMethodName
{
[classVariableName doSomething];
}
-(void) instanceMethodName
{
[classVariableName doSomething];
}
...
@end
Références :
À partir de Xcode 8, vous pouvez définir les propriétés de classe dans Obj-C. Cela a été ajouté pour interagir avec les propriétés statiques de Swift.
Objective-C prend désormais en charge les propriétés de classe, qui interagissent avec les propriétés de type Swift. Elles sont déclarées sous la forme: @property (class) NSString * someStringProperty ;. Elles ne sont jamais synthétisées. (23891898)
Voici un exemple
@interface YourClass : NSObject
@property (class, nonatomic, assign) NSInteger currentId;
@end
@implementation YourClass
static NSInteger _currentId = 0;
+ (NSInteger)currentId {
return _currentId;
}
+ (void)setCurrentId:(NSInteger)newValue {
_currentId = newValue;
}
@end
Ensuite, vous pouvez y accéder comme ceci:
YourClass.currentId = 1;
val = YourClass.currentId;
Voici un très intéressant article explicatif J'ai utilisé comme référence pour éditer cette ancienne réponse.
2011 Réponse: (ne l'utilisez pas, c'est terrible)
Si vous ne voulez vraiment pas déclarer une variable globale, il existe une autre option, peut-être pas très orthodoxe :-), mais qui fonctionne ... Vous pouvez déclarer une méthode "get & set" comme celle-ci, avec une variable statique à l'intérieur:
+ (NSString*)testHolder:(NSString*)_test {
static NSString *test;
if(_test != nil) {
if(test != nil)
[test release];
test = [_test retain];
}
// if(test == nil)
// test = @"Initialize the var here if you need to";
return test;
}
Donc, si vous avez besoin d'obtenir la valeur, appelez simplement:
NSString *testVal = [MyClass testHolder:nil]
Et puis, quand vous voulez le définir:
[MyClass testHolder:testVal]
Dans le cas où vous voulez pouvoir définir cette pseudo-static-var à nil, vous pouvez déclarer testHolder
comme ceci:
+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
static NSString *test;
if(shouldSet) {
if(test != nil)
[test release];
test = [_test retain];
}
return test;
}
Et deux méthodes pratiques:
+ (NSString*)test {
return [MyClass testHolderSet:NO newValue:nil];
}
+ (void)setTest:(NSString*)_test {
[MyClass testHolderSet:YES newValue:_test];
}
J'espère que ça aide! Bonne chance.
Sur votre fichier .m, vous pouvez déclarer une variable comme statique:
static ClassName *variableName = nil;
Ensuite, vous pouvez l’initialiser sur votre méthode +(void)initialize
.
Veuillez noter qu'il s'agit d'une variable statique C simple et qu'elle n'est pas statique au sens Java ou C # l'examine, mais produira des résultats similaires.
Dans votre fichier .m, déclarez une variable globale de fichier:
static int currentID = 1;
puis dans votre routine init, notez que:
- (id) init
{
self = [super init];
if (self != nil) {
_myID = currentID++; // not thread safe
}
return self;
}
ou si cela doit changer à un autre moment (par exemple dans votre méthode openConnection), incrémentez-le ensuite. N'oubliez pas qu'il n'est pas thread-safe tel quel, vous devrez faire une synchronisation (ou, mieux encore, utiliser un ajout atomique) s'il peut y avoir un problème de thread.
Comme l'a dit pgb, il n'y a pas de "variables de classe", seulement des "variables d'instance". La méthode objective-c des variables de classe est une variable globale statique située dans le fichier .m de la classe. Le "statique" garantit que la variable ne peut pas être utilisée en dehors de ce fichier (c'est-à-dire qu'elle ne peut pas être externe).
Voici une option:
+(int)getId{
static int id;
//Do anything you need to update the ID here
return id;
}
Notez que cette méthode sera la seule méthode pour accéder à id, vous devrez donc la mettre à jour d'une manière ou d'une autre dans ce code.
(À proprement parler, il ne s'agit pas d'une réponse à la question mais, d'après mon expérience, il peut être utile de rechercher des variables de classe.)
Une méthode de classe peut souvent jouer de nombreux rôles qu'une variable de classe jouerait dans d'autres langues (par exemple, une configuration modifiée au cours des tests):
@interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
@end
@implementation
+ (NSString*)theNameThing { return @"Something general"; }
- (void)doTheThing {
[SomeResource changeSomething:[self.class theNameThing]];
}
@end
@interface MySpecialCase: MyCls
@end
@implementation
+ (NSString*)theNameThing { return @"Something specific"; }
@end
Maintenant, un objet de classe MyCls
appelle Resource:changeSomething:
avec la chaîne @"Something general"
sur appel de doTheThing:
, mais un objet dérivé de MySpecialCase
avec la chaîne @"Something specific"
.
vous pouvez renommer la classe classA.mm et y ajouter des fonctionnalités C++.
Une autre possibilité serait d’avoir un petit singleton NSNumber
sous-classe.