2009-06-30 7 views
139

J'ai un film de classe, dont chacun stocke un ID unique. En C#, Java etc, je peux définir un staticID currentID et chaque fois que je mets l'ID je peux augmenter le currentID et le changement se produit au niveau de la classe et non au niveau de l'objet. Cela peut-il être fait dans l'objectif C? J'ai trouvé très difficile de trouver une réponse à cela.Objective C Static Classe Variables de niveau

Répondre

28

Sur votre fichier .m, vous pouvez déclarer une variable statique:

static ClassName *variableName = nil; 

Ensuite, vous pouvez l'initialiser sur votre méthode +(void)initialize.

S'il vous plaît noter que ceci est une variable statique plaine C et n'est pas statique au sens Java ou C# considérer, mais donnera des résultats similaires.

+3

Veuillez corriger: '+ (void) initialize' est la méthode – monkeydom

11

Comme dit PGB, il n'y a pas de "variables de classe," seulement "variables d'instance." La méthode objective-c de faire des variables de classe est une variable globale statique dans le fichier .m de la classe. Le caractère "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 extern).

16

Dans votre fichier .m, déclarez une variable globale du fichier:

static int currentID = 1; 

puis dans votre routine d'initialisation, refernce que:

- (id) init 
{ 
    self = [super init]; 
    if (self != nil) { 
     _myID = currentID++; // not thread safe 
    } 
    return self; 
} 

ou si elle doit changer à un autre moment (par exemple dans votre méthode openConnection), puis l'incrémenter là. Rappelez-vous que ce n'est pas sûr comme thread, vous devrez faire de la syncronisation (ou mieux encore, utiliser un ajout atomique) s'il y a des problèmes de threading.

155

Problème Description:

  1. Vous voulez que votre ClassA d'avoir une variable de classe ClassB.
  2. Vous utilisez Objective-C comme langage de programmation.
  3. Objective-C ne supporte pas les variables de classe comme le fait C++.

Une alternative:

Simuler un comportement variable de classe en utilisant Objective-C Caractéristiques

  1. Declare/Définir une variable statique dans le classA.m il sera accessible que pour les les méthodes classA (et tout ce que vous mettez dans classA.m).

  2. la Ecraser NSObject méthode initialize de classe pour initialiser une fois la variable statique avec une instance de ClassB.

  3. Vous vous demanderez, pourquoi devrais-je remplacer la méthode initialize NSObject. La documentation Apple sur cette méthode a la réponse: "Le moteur d'exécution envoie une initialisation à chaque classe dans un programme exactement une fois juste avant que la classe, ou toute classe qui en hérite, envoie son premier message depuis le programme. ne peut jamais être invoqué si la classe n'est pas utilisée.) ".

  4. Sentez-vous libre d'utiliser la variable statique dans une méthode de classe/instance 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:

  1. Class variables explained comparing Objective-C and C++ approaches
+3

Pouvez-vous avoir une variable statique de Type ClassA dans classA.m? – goatlinks

+0

@goatlinks - Oui. – DougW

+6

cela pourrait être une question stupide, mais qu'en est-il de la libération de la mémoire? n'a pas d'importance, car il doit vivre aussi longtemps que l'application est en cours d'exécution? – samiq

26

A partir de Xcode 8, vous pouvez définir des propriétés de classe dans Obj-C. Cela a été ajouté pour interopérer 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.

Ils sont déclarés comme: @property (class) NSString * someStringProperty ;. Ils ne sont jamais synthétisés. (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 explanatory post très intéressant, j'utilisé comme référence pour modifier ce vieux répondre.


2011 Réponse: (ne pas utiliser, il est terrible)

Si vous avez vraiment ne voulez vraiment pas déclarer une variable globale, il y a une autre option, peut-être pas très orthodoxe: -), mais fonctionne ... vous pouvez déclarer « obtenir & ensemble » méthode comme celui-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 pour obtenir la valeur, il suffit d'appeler:

NSString *testVal = [MyClass testHolder:nil] 

Et puis, quand vous voulez régler:

[MyClass testHolder:testVal] 

Dans le cas où vous voulez être en mesure de définir cette pseudo-statique var à zéro, 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]; 
} 

Hope it helps! Bonne chance.

+0

Cool, mais ce n'est pas vraiment une variable globale car elle ne peut pas être accédée à partir d'autres fichiers '.m', et je pense que c'est bien qu'elle soit" globale "dans le fichier' Class.m'. – ma11hew28

3

Voici serait 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 d'accès id, donc vous devrez le mettre à jour en quelque sorte dans ce code.

0

Vous pouvez renommer la classe en classe A.mm et ajouter des fonctionnalités C++ en elle.

2

(pas à proprement parler une réponse à la question, mais dans mon expérience susceptible d'être utile lors de la recherche pour les variables de classe)

Une méthode de classe peut souvent jouer plusieurs des rôles une variable de classe serait dans d'autres langues (par exemple changé la configuration lors des essais):

@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 appels Resource:changeSomething: avec la chaîne @"Something general" lors d'un appel à doTheThing:, mais un objet dérivé de MySpecialCase avec la chaîne @"Something specific" .

0

Une autre possibilité serait d'avoir un petit singleton de sous-classe NSNumber.

Questions connexes