Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Tutorials

Reply
 
LinkBack Thread Tools Display Modes
Old 07-27-2010, 09:55 AM   #1 (permalink)
Registered Member
 
Join Date: Jun 2009
Location: Ypsilanti, Michigan
Age: 63
Posts: 1,526
Default Global variables

Global variables are data items whose scope is the entire application. That means you can access them from anywhere in your code. Whenever global variables are discussed among object-oriented programmers, you often see dire warnings that global variables are dangerous to use and should be completely avoided. There is some truth to this warning, but it should be taken with a little moderation. Global variables do indeed offer opportunities for abuse by careless programmers. But every application has some variables that are in function, if not in fact, global.

I want to start by looking at global variables of primitive data types. These are int, char, float, BOOL, etc. Globals of this type can be handled just as they would be in a plain C-language program.

Setting up a global variable involves both a declaration and a definition. The declaration is what happens in a .H file and its purpose is to tell the rest of the code that this variable exists and what type it is (int, char, BOOL, or whatever), and it is done with an "extern" statement. If you have only looked at pure Objective-C .H files, you may think that everything in that file needs to be between the @interface statement and the @end statement for some class. But that is not true. You can have things before the @interface or after the @end, and they will be treated as ordinary C language declarations. So in some .H file (it does not matter which one), write:

Code:
extern int globalGameLevel;
@interface ...
...
@end
Note that the "extern" statement is before the @interface statement, so it is not part of the class being declared, but is actually global. This will declare a int called globalGameLevel that any code that includes this .H file will now know how to access. However this is only the declaration. It does not actually set aside any memory for globalGameLevel. It is more like a promise that you intend to define globalGameLevel somewhere else. And that somewhere else is a .M file (it does not matter which one). Just as with the .H file, the .M file can have stuff in it that is not between the @implementation and the @end statements. In this example, I am going to put the definition of globalGameLevel after the @end statement, but it could just as well go at the top of the file:

Code:
@implementation ...
...
@end
int globalGameLevel;
This actually sets aside memory in your app for globalGameLevel, and is the fulfillment of the promise we made when we declared globalGameLevel in the .H file.

Now that the globalGameLevel variable has been declared and defined, it can be accessed simply as globalGameLevel from anywhere in your code. You can do the same thing with other primitive data types, as well as arrays of primitive data types (C-style arrays, not NSArrays), and even structures (struct). Objective C is a superset of C so anything that you could do in C you can do in Objective C.

- - - - - - - - - - - -

Now I want to look at a more controversial (and risky) use of globals: global Objective-C objects. Unlike the primitive data types discussed above, these data types are not defined statically (except for constant NSStrings which appear as @"..."). Generally, such objects can only be allocated dynamically by your app as it runs. So in that sense there can be no such thing as a global NSObject. But there can be a global pointer to a NSObject. Suppose we took the pattern shown above for primitive data types and tried to apply it to Objective-C object types. Suppose, for instance, that we declared in some .H file:

Code:
extern NSString *userName;
@interface ...
...
@end
and then, in some .M file, we put:

Code:
@implementation ...
...
@end
NSString *userName;
This would declare and define a variable called userName, which is supposed to be a pointer to a NSString object. The "*" before userName says that userName is a pointer. Memory for that pointer would be statically allocated by the compiler before the program runs. But what would that pointer start out pointing at? The answer is nothing. userName will have the value nil. So it would have to be made to point to somewhere valid before it can be used. Suppose that somewhere at the beginning of our app we set:

Code:
userName = [[NSString alloc] initWithFormat: @"Joe%1d", 7];
This would dynamically allocate memory for a NSString object, giving it the value "Joe7". Then from anywhere in the app I could reference userName and get the value "Joe7", and it would all be perfectly legal.

Why is this so risky? There are a number of issues. For one thing, you have to be very sure that userName is set somewhere before you attempt to use it. Otherwise you will be attempting to access a NSString through a nil pointer, which will result in a crash. Another problem is what happens if userName is reassigned? Suppose that later on in the program we wrote:

Code:
userName = [[NSString alloc] initWithFormat: @"Susan%1d", 5];
This would make the global pointer, userName, point at a new string whose value is "Susan5". But what about the "Joe7" string? The memory for that string would still be allocated, buy now nobody can use that memory because nothing is pointing at it. This is a memory leak, and it must be avoided.

If we were not dealing with globals, but rather with properties of NSObjects, then we could rely on the synthesized setter to properly handle releasing of the old target of the pointer before a new target is assigned. But with a global pointer, we cannot do that because it cannot be a property because it does not belong to any class. Of course you could construct your own setter-like function for the global variable, userName:

Code:
void setUserName( NSString *newVal )
{
  [newVal retain];
  [userName release];
  userName = newVal;
}
Notice that this is not an objective-C method, but rather a C-language function. The parameter is enclosed with parentheses rather than following a colon, and the return type, void, is written without parentheses, and there is no "+" or "-" at the start, as there would be for an Objective-C method. Also, this function would have to be declared and defined just like the global variable, outside of any classes. Then you would have to promise yourself that you would never set userName except through this function. Or, if you didn't want to use the global setter function, you would have to promise yourself that you will set userName once and only once in the lifetime of your app. This is all very risky. But there is a safer approach.

The safer approach to global Objective-C objects is to make them properties of the App Delegate. There is only one App Delegate object in your app, and it is accessible from anywhere. So you could write:


Code:
@interface MyAppDelegate : NSObject  {
  NSString *userName;
}
@property (nonatomic, retain) NSString *userName;
...
@end
and in the .M file for the App Delegate you would write:

Code:
@implementation MyAppDelegate
@synthesize userName;
...
@end
Then, whenever you want to fetch or write userName, you would write:

Code:
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
someClass.someString = appDelegate.userName;  //..to fetch
appDelegate.userName = ..some NSString..;     //..to write
Robert Scott
Ypsilanti, Michigan

Last edited by RLScott; 08-02-2010 at 11:26 AM.
RLScott is offline   Reply With Quote
Old 09-21-2010, 11:20 PM   #2 (permalink)
Registered Member
 
Join Date: Sep 2010
Posts: 10
Red face Thanks

Thanks for the post. It really helped me
PoojaBohora is offline   Reply With Quote
Old 10-07-2010, 10:23 AM   #3 (permalink)
iOS Developer Trainer
 
Join Date: Dec 2008
Location: Northeast United States
Posts: 141
Send a message via AIM to MattjDrake Send a message via Skype™ to MattjDrake
Default Great Tutorial

Trying to deal with global variables is a pretty vexing topic. It seems like you need to use them every once in a while.
__________________
How To Make iPhone Apps
http://howtomakeiphoneapps.com
Cocoa-Touch, iPad & iPhone Programming Videos, Tutorials & How-To exclusively for new app developers
MattjDrake is offline   Reply With Quote
Old 02-10-2011, 12:00 AM   #4 (permalink)
NMF
Registered Member
 
Join Date: Feb 2011
Location: Colorado
Posts: 1
Question Global NSArray

Hey Robert,

Thanks for taking the time to write out this post it was helpful for me to understand how objective C works. I used your method explained in the post to try and create a global NSArray that I could share across views.

//In my first view in the "viewDidLoad" method I do
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
//I then set my array with 14 strings
appDel.delArray = viewArray;
//I then ensure the array has something in it
NSLog(@"Count: %d", [appDel.test count]);
//which returns 14

//I then go to my second view in the "viewDidLoad" method I do
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
//At this point I expect that my array should have 14 strings in it
NSLog(@"Count: %d", [appDel.test count]);
//But the above line returns 0 and I am not sure where I am going wrong

I did the same process with an NSString just to see what would happen. I set it in one view and get it in the second and it works with no problems. Can you provide advice on creating a global NSArray or NSMutableArray (is what I really want) across multiple views? I also tried doing it using a singleton class with no luck, once again other objects worked just not array objects. Thanks in advance for any help you can provide.
NMF is offline   Reply With Quote
Old 02-15-2011, 04:40 AM   #5 (permalink)
Registered Member
 
Join Date: Sep 2010
Posts: 10
Default

Quote:
Originally Posted by NMF View Post
Hey Robert,

Thanks for taking the time to write out this post it was helpful for me to understand how objective C works. I used your method explained in the post to try and create a global NSArray that I could share across views.

//In my first view in the "viewDidLoad" method I do
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
//I then set my array with 14 strings
appDel.delArray = viewArray;
//I then ensure the array has something in it
NSLog(@"Count: %d", [appDel.test count]);
//which returns 14

//I then go to my second view in the "viewDidLoad" method I do
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
//At this point I expect that my array should have 14 strings in it
NSLog(@"Count: %d", [appDel.test count]);
//But the above line returns 0 and I am not sure where I am going wrong

I did the same process with an NSString just to see what would happen. I set it in one view and get it in the second and it works with no problems. Can you provide advice on creating a global NSArray or NSMutableArray (is what I really want) across multiple views? I also tried doing it using a singleton class with no luck, once again other objects worked just not array objects. Thanks in advance for any help you can provide.
Hello,
Have you allocated memory for the array which is declared in appdelegate?
PoojaBohora is offline   Reply With Quote
Old 02-15-2011, 04:45 AM   #6 (permalink)
Registered Member
 
Join Date: Sep 2010
Posts: 10
Default

Have you allocated memory for array which is allocated in appdelegate?
PoojaBohora is offline   Reply With Quote
Old 02-23-2011, 01:36 PM   #7 (permalink)
Registered Member
 
Join Date: Nov 2009
Posts: 110
Default asdfasdf

Quote:
Originally Posted by MattjDrake View Post
Trying to deal with global variables is a pretty vexing topic. It seems like you need to use them every once in a while.
This is so true. I know this might be grave dig but this is one of the most helpful topics ever thank you!!!
paluter is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 260
23 members and 237 guests
@sandris, AdamL, ADY, Dani77, diyora, FAED, fredidf, F_Bryant, GHuebner, HDshot, headkaze, JasonR, mer10, Oral B, prchn4christ, Rudy, smithdale87, stekki, tgjorgoski, Thompson22, Touchmint, twerner, vigu360
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 158,880
Threads: 89,228
Posts: 380,752
Top Poster: BrianSlick (7,129)
Welcome to our newest member, @sandris
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 01:01 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0