Correct way to declare Global vars

I recently came across a piece of obj-C code that looked something like this:-


#import "LocationSeeker.h"

@interface LocationSeeker ()

@end
NSString *const LocationSeekerMapTypePrefKey= @"LocationSeekerMapTypePrefKey";
NSString *const CenterCoordinateLatitudePrefKey= @"CenterCoordinateLatitudePrefKey";
NSString *const CenterCoordinateLongitudePrefKey= @"CenterCoordinateLongitudePrefKey";

@implementation LocationSeeker

+(void)initialize{//used for making factory settings
    NSLog(@"initializing custom factory settings");
    //THE factory settings are not saved to disk.. These effect at runtime..
    NSMutableDictionary *defaults= [NSMutableDictionary dictionary];
    //Setting the default as Hybrid view for map
     ......
 }

-(IBAction)buttonDidGetPressed:(id)sender{
    NSLog(@"%@",NSStringFromSelector(_cmd));
    NSLog(@"%@",sender);
    
    [[NSUserDefaults standardUserDefaults] setInteger:[sender selectedSegmentIndex] forKey:WhereamiMapTypePrefKey];
    if([sender selectedSegmentIndex]==0){
        [worldView setMapType:MKMapTypeStandard];
    }........
    .....
}


In the code above, there are 3 constants declared at a global level. What i wanted to inquire was whether this is the correct place to declare and define globals. Shouldn't these be declared and defined inside @implementation LocationSeeker ? Like this:

#import "LocationSeeker.h"

@interface LocationSeeker ()

@end
@implementation LocationSeeker
NSString *const LocationSeekerMapTypePrefKey= @"LocationSeekerMapTypePrefKey";
NSString *const CenterCoordinateLatitudePrefKey= @"CenterCoordinateLatitudePrefKey";
NSString *const CenterCoordinateLongitudePrefKey= @"CenterCoordinateLongitudePrefKey";

+(void)initialize{//used for making factory settings
    NSLog(@"initializing custom factory settings");
    //THE factory settings are not saved to disk.. These effect at runtime..
    NSMutableDictionary *defaults= [NSMutableDictionary dictionary];
    //Setting the default as Hybrid view for map
     ......
 }

What are the effects of the difference between the 2 approaches?

Accepted Reply

It doesn’t matter where the globals are declared in this case.


Global variables are a C construct, not Obj-C specifically. That means their semantics don’t depend on the class structure. In other languages, the fact that the declaration was inside a class would make it part of the class, but that’s not true of C globals.


There is one exception to this. If you declare a static variable at file scope (so it’s like a global but isn’t doesn have external linkage), and if it’s declared inside an @implementation block, then it’s private to the class. Code outside the @implementation block in the same file can’t reference the static variable. If it’s declared outside the @implementation block, it’s available to all code in the same file.


But that’s a hack for static in Obj-C. In general, C rules apply.

Replies

My understanding (but I'm not very fluent in objC), is that var must be declared in interface, but could be initialized in implementation


ex: h ttps://gist.github.com/ykka/4094782

or

h ttps://www.quora.com/Can-I-declare-NSString-type-objects-as-global-variable-in-Objective-C


Difference is that var not defined in .h won't be visible on other modules (which is the purpose of a global)

It doesn’t matter where the globals are declared in this case.


Global variables are a C construct, not Obj-C specifically. That means their semantics don’t depend on the class structure. In other languages, the fact that the declaration was inside a class would make it part of the class, but that’s not true of C globals.


There is one exception to this. If you declare a static variable at file scope (so it’s like a global but isn’t doesn have external linkage), and if it’s declared inside an @implementation block, then it’s private to the class. Code outside the @implementation block in the same file can’t reference the static variable. If it’s declared outside the @implementation block, it’s available to all code in the same file.


But that’s a hack for static in Obj-C. In general, C rules apply.

So the globals consts in the code above, could have been declared and defined inside the @implementation block and it wouln't have made a difference? In that case, if additionally they were static, it wouldn't have been possible to be referenced from outside of the implementation block? Could you please exemplify such kind of a situation with a code snippet?

In most cases, there’s no real benefit. You have to get a bit creative to construct a use case that has some value. Generally, putting static bars inside the implementation block only makes sense if there are multiple implementation blocks in the same file.


For example, a KVO context value is something that’s often a static variable:


static void* context = &context // typical declaration


If two classes each need a context, it might be thought to be “clean” to hide them inside the implementation block. In a way, these are just class variables, and real class variables are probably more common these days.