Using Global Variables in Objective-C

How to use global variables in Objective-C?

Traditionally, global variables are declared in a header, and defined in a source file. Other source files only need to know how it is declared to use it (i.e. its type and its name). As long as the variable is defined somewhere in a source file, the linker will be able to find it and appropriately link all the references in other source files to the definition.

Somewhere in your header, you would declare a global variable like this:

extern int GlobalInt;

The extern part tells the compiler that this is just a declaration that an object of type int identified by GlobalInt exists. It may be defined later or it may not (it is not the compiler's responsibility to ensure it exists, that is the linker's job). It is similar to a function prototype in this regard.

In one of your source files, you define the GlobalInt integer:

int GlobalInt = 4;

Now, each file that includes the header will have access to GlobalInt, because the header says it exists, so the compiler is happy, and the linker will see it in one of your source files, so it too will be happy. Just don't define it twice!

However


You should consider whether or not this approach is useful. Global variables get messy for a number of reasons (trying to find out exactly where it is defined or declared, threading issues), there is usually not a need for global variables. You should perhaps consider using a singleton approach.

Global variable in Objective-C program

For a standard global variable (not persistent when the app is terminated and restarted) add this to a header file (*.h) of your choice:

extern NSInteger MYGlobalVariable;

Then put this in the implementation file; (*.m, *.c, *.cpp):

MYGlobalVariable = 0;  // Or any other default value.

That is how you do a bread and butter global variable.

Using global variables in Objective-C

One way to implement global variables, and to manage their lifetime (i.e. that they are initialized) and even to provide global methods is to implement a class exposing those variables/methods and to use the singleton pattern:

GlobalVars.h:

#import <Foundation/Foundation.h>

@interface GlobalVars : NSObject
{
NSMutableArray *_truckBoxes;
NSMutableArray *_farmerlist;
NSString *_farmerCardNumber;
NSString *_fName;
}

+ (GlobalVars *)sharedInstance;

@property(strong, nonatomic, readwrite) NSMutableArray *truckBoxes;
@property(strong, nonatomic, readwrite) NSMutableArray *farmerList;
@property(strong, nonatomic, readwrite) NSString *farmerCardNumber;
@property(strong, nonatomic, readwrite) NSString *fName;

@end

GlobalVars.m:

#import "GlobalVars.h"

@implementation GlobalVars

@synthesize truckBoxes = _truckBoxes;
@synthesize farmerList = _farmerList;
@synthesize frameCardNumber = _frameCardNumber;
@synthesize fName = _fName;

+ (GlobalVars *)sharedInstance {
static dispatch_once_t onceToken;
static GlobalVars *instance = nil;
dispatch_once(&onceToken, ^{
instance = [[GlobalVars alloc] init];
});
return instance;
}

- (id)init {
self = [super init];
if (self) {
_truckBoxes = [[NSMutableArray alloc] init];
_farmerlist = [[NSMutableArray alloc] init];
// Note these aren't allocated as [[NSString alloc] init] doesn't provide a useful object
_farmerCardNumber = nil;
_fName = nil;
}
return self;
}

@end

You can then use these global variables like this, for example:

GlobalVars *globals = [GlobalVars sharedInstance];
globals.fName = @"HelloWorld.txt";
[globals.farmerList addObject:@"Old Macdonald"];
[self processList:[globals farmerList]];

However, please consider:

  • You don't need to use global variables like this; you should be able to create a model object which is created as necessary and reference to it passed to the views. This is MVC.
  • You also posted a stack trace of an unrelated issue which is extremely common with Objective-C; only you can fix this error, once you realize what it is.

What is the proper way to declare a global variable in Objective-C

Declaring variables inside curly braces is actually declaring an instance variable or "ivar" for short. That is, a variable that's local to instances of your class.

This used to only be possible after @interface declarations, which is why you sometimes see it there. This changed around Xcode 4 so that you can now do it after @implementation also. As far as I'm aware, this is just stylistic preference. ivars are never accessible outside a class (in theory. Technically, everything is accessible to everything in C), so defining them in the .h won't make them public. It does expose an implementation detail, though, which is why most code I see now that uses them puts them in the @implementation.

But I don't see them much in code anymore. Because when you define a @property what is actually happening under the covers is an ivar, a getter method, and a setter method are all actually being synthesized for you. The getter and setter methods just get the value of the ivar and set the value of the ivar, respectively.

So if what you want is something that has the same scope as a property, but doesn't come with the -myVar and -setMyVar: methods, then this is the right way to go.

But you probably shouldn't want that. There are a whole bunch of reasons that it's nice to only access ivars through accessor methods. It lets you override functionality, translate values, and all the other sorts of fun things abstraction affords you.

If what you want is a @property that isn't accessible outside the class, just declare it in a class extension:

//In MyClass.m
@interface MyClass()
@property NSNumber *myProperty;
@end

@implementation MyClass
//All your implementation stuff here.
@end

Because it's not in the .h file, it won't be "visible" to other classes (In theory. See above about everything being visible in C).

If on the other hand, what you really truly want is something that is really truly global (hint: you shouldn't. Global variables are generally a smell of bad design), you need to define it at the top of your file outside any @interface or @implementation blocks.

Another related tidbit: To define a "global" variable with a scope limited to a given file, look into C's static keyword. It's interesting.

Swift globals and global functions in objective c

Here is the document about it

You’ll have access to anything within a class or protocol that’s
marked with the @objc attribute as long as it’s compatible with
Objective-C. This excludes Swift-only features such as those listed
here:

  • Generics
  • Tuples
  • Enumerations defined in Swift
  • Structures defined in Swift
  • Top-level functions defined in Swift
  • Global variables defined in Swift
  • Typealiases defined in Swift
  • Swift-style variadics
  • Nested types
  • Curried functions

Global variables (including constants) are unaccessible from Objective-C.

Instead, you have to declare a class which has accessors for the global constants.

// Swift
public let CARDS = ["card1", "card2"]

@objc class AppConstant {
private init() {}
class func cards() -> [String] { return CARDS }
}

// Objective-C
NSArray *cards = [AppConstant cards];

Using global variables in objective c

Consider you want to send string data to ViewController2,ViewController3 from ViewController1.

Make property of the string variable in ViewController2 and ViewController3.

@property(nonatomic,strong) NSString *str;

And while pushing the ViewController2 and ViewController3:

ViewController2 *viewController = [ViewController2 alloc]init];
viewController2.str = @"Some text";
[self.navigationController pushViewController:viewController2 animated:YES];

And you have the data send from ViewController1 in ViewController2.

In Objective-C, how do you declare/use a global variable?

Objective-C is a superset of C, so just do it the C way:

int globalX = 100;

And header file:

extern int globalX;

Objective C - Global variables for every View Controller

I would personally advise you to use the Singleton pattern.

I would not recommend putting everything into AppDelegate, this class is not meant for that.

Instead, what you can do is create a dedicated class (with a name like "ApplicationState", or whatever suits you), and put the properties you need in its header file, and having your singleton management code in the .m (and the prototype in the header)

If you need the singleton management code, here it is:

+ (ApplicationState*)sharedInstance
{
static ApplicationState* sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}

Then, if you have in the header:

@property (nonatomic, strong) NSObject* object;

+ (ApplicationState*)sharedInstance;

You will be able to get this variable from anywhere by including the ApplicationState header file, and call:

[[ApplicationState sharedInstance] object];


Related Topics



Leave a reply



Submit