Question sur la portée des variables globales

Bonjour à  tous !


 


Ce matin, j'ai remarqué que



@implementation MyCBDSegmentedControl
{
static BOOL _touchBegan;
static BOOL _reactOnTouchBegan;
}

provoquait une erreur "type name does not allow storage class to be specified" alors que 



@implementation MyCBDSegmentedControl

static BOOL _touchBegan;
static BOOL _reactOnTouchBegan;


non.


 


Cela voudrait-il dire que si les variables sont dans les accolades elles sont automatiquement "locales à  cette classe" ? Est-ce que enlever les accolades ou les mettre va changer profondément le sens du code ?


 


C'est ce code de SO qui me fait poser la question. 



@interface CustomSegmentedControl : UISegmentedControl
@end




@implementation CustomSegmentedControl{


BOOL _touchBegan;
BOOL _reactOnTouchBegan;
}



- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

_touchBegan = YES;

NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
if (_reactOnTouchBegan) {
// before iOS7 the segment is selected in touchesBegan
if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
}


-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

_touchBegan = NO;

NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
[super touchesEnded:touches withEvent:event];
if (!_reactOnTouchBegan) {
CGPoint locationPoint = [[touches anyObject] locationInView:self];
CGPoint viewPoint = [self convertPoint:locationPoint fromView:self];
if ([self pointInside:viewPoint withEvent:event]) {
// on iOS7 the segment is selected in touchesEnded
if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
}
}


- (void)sendActionsForControlEvents:(UIControlEvents)controlEvents {
if(controlEvents == UIControlEventValueChanged){
_reactOnTouchBegan = _touchBegan;
}
[super sendActionsForControlEvents:controlEvents];
}


@end

p2j765fh.gif


Réponses

  • CéroceCéroce Membre, Modérateur
    Dans le premier cas, tu déclares un classe, un "moule" pour un objet. Tout objet aura deux variables d'instance _touchBegan et _reactOnTouchBegan. Ce sont des variables d'instance, donc chaque instance possède ses propres exemplaires de ces variables.

    Dans le second cas, tu définis des variables globales: elles sont accessibles à  tout le processus, et elles n'existent qu'en un seul exemplaire.
  • OK @Céroce !


     


    Et, dans le second cas, que cela changera-t-il si j'enlève le static ?


    Si dans un autre .m je déclare des variables avec le même nom (et le même type, et aussi sans static), alors le BOOL global de cette classe et le BOOL global de l'autre classe seront les mêmes ? C'est ça ?


     


    Le static permet de nommer des variables globales différentes avec le même nom, dans deux .m différents, c'est ça ?


  • zoczoc Membre
    octobre 2014 modifié #4

    Alors attention, les variables globales static ne sont pas exportées lors de la compilation du fichier. Donc elles ne sont visibles que dans le fichier .m dans lequel elles sont déclarées.


    Les variables globales non static sont exportées et visibles dans l'ensemble du module binaire. Elles doivent être référencées avec le mot clé extern dans les autres fichiers sources pour éviter une collision...


    exemple:


    fichier F1.m :

     



    BOOL aGlobalBool;

    fichier F2.m (ou mieux dans un .h inclus par le fichier source) :

     



    extern BOOL aGlobalBool;

  • AliGatorAliGator Membre, Modérateur
    octobre 2014 modifié #5
    Si tu mets entre accolades, c'est local. En particulier, si tu mets dans des accolades après le @interface (ou après le @implementation) alors ça va être une variable d'instance de la classe.
    Et dans ce contexte, le mot clé "static" n'a pas de sens (d'où sans doute l'erreur que tu as d'ailleurs).

    Si tu mets en dehors des accolades, c'est global. Pas lié à  la classe. Et dans ce cas, si tu mets le mot clé "static", c'est lié au fichier et ne sera pas visible depuis un autre fichier source. Par contre, comme c'est global, toutes les instances partageront la même variable, vu qu'elle n'est pas lié à  ton instance.

    Voir aussi SO
  • Joanna CarterJoanna Carter Membre, Modérateur

    Depuis Objective-C 2.0, il est conseillé de ne pas declarer le ivars entre les accolades. Par contre, utiliser les @property soit dans l'interface (publique) soit dans un "class extension" de l'implementation (privé)


Connectez-vous ou Inscrivez-vous pour répondre.