Global variables

Instead of using #define, Objective-C programmers commonly use global variables to hold constant values.

Let’s add to your program to explain. First, there is a class named NSLocale that stores information about different geographical locations. You can get an instance of the user’s current locale and then ask it questions. For instance, if you wanted to know what the currency is in the user’s locale, you could ask for it like this:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​

i​n​t​ ​m​a​i​n​ ​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​​u​0​3​c​0​ ​i​s​ ​%​f​"​,​ ​M​_​P​I​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​%​d​ ​i​s​ ​l​a​r​g​e​r​"​,​ ​M​A​X​(​1​0​,​ ​1​2​)​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​c​a​l​e​ ​*​h​e​r​e​ ​=​ ​[​N​S​L​o​c​a​l​e​ ​c​u​r​r​e​n​t​L​o​c​a​l​e​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​c​u​r​r​e​n​c​y​ ​=​ ​[​h​e​r​e​ ​o​b​j​e​c​t​F​o​r​K​e​y​:​@​"​c​u​r​r​e​n​c​y​"​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​M​o​n​e​y​ ​i​s​ ​%​@​"​,​ ​c​u​r​r​e​n​c​y​)​;​

 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Build and run it. Depending on where you are, you should see something like

M​o​n​e​y​ ​i​s​ ​U​S​D​

If, however, you mistype the key as @"Kuruncy", you won’t get anything back. To prevent this problem, the Foundation framework defines a global variable called NSLocaleCurrencyCode. It isn’t easier to type, but if you do mistype it, the compiler will complain. Also, code completion in Xcode works properly for a global variable, but not for the string @"currency". Change your code to use the constant:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​

i​n​t​ ​m​a​i​n​ ​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​​u​0​3​c​0​ ​i​s​ ​%​f​"​,​ ​M​_​P​I​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​%​d​ ​i​s​ ​l​a​r​g​e​r​"​,​ ​M​A​X​(​1​0​,​ ​1​2​)​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​c​a​l​e​ ​*​h​e​r​e​ ​=​ ​[​N​S​L​o​c​a​l​e​ ​c​u​r​r​e​n​t​L​o​c​a​l​e​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​c​u​r​r​e​n​c​y​ ​=​ ​[​h​e​r​e​ ​o​b​j​e​c​t​F​o​r​K​e​y​:​N​S​L​o​c​a​l​e​C​u​r​r​e​n​c​y​C​o​d​e​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​M​o​n​e​y​ ​i​s​ ​%​@​"​,​ ​c​u​r​r​e​n​c​y​)​;​

 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

When the class NSLocale was written, this global variable appeared in two places. In NSLocale.h, the variable was declared something like this:

e​x​t​e​r​n​ ​N​S​S​t​r​i​n​g​ ​c​o​n​s​t​ ​*​N​S​L​o​c​a​l​e​C​u​r​r​e​n​c​y​C​o​d​e​;​

The const means that this pointer will not change for the entire life of the program. The extern means I promise this exists, but it will be defined in some other file. And sure enough, in the file NSLocale.m, there is a line like this:

N​S​S​t​r​i​n​g​ ​c​o​n​s​t​ ​*​N​S​L​o​c​a​l​e​C​u​r​r​e​n​c​y​C​o​d​e​ ​=​ ​@​"​c​u​r​r​e​n​c​y​"​;​

enum

Often you will need to define a set of constants. For example, imagine that you were developing a blender with five speeds: Stir, Chop, Liquefy, Pulse, and Ice Crush. Your class Blender would have a method called setSpeed:. It would be best if the type indicated that only one of the five speeds was allowed. To do this, you would define an enumeration:

e​n​u​m​ ​B​l​e​n​d​e​r​S​p​e​e​d​ ​{​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​S​t​i​r​ ​=​ ​1​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​C​h​o​p​ ​=​ ​2​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​L​i​q​u​i​f​y​ ​=​ ​5​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​P​u​l​s​e​ ​=​ ​9​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​I​c​e​C​r​u​s​h​ ​=​ ​1​5​
}​;​

@​i​n​t​e​r​f​a​c​e​ ​B​l​e​n​d​e​r​ ​:​ ​N​S​O​b​j​e​c​t​
{​
 ​ ​ ​ ​/​/​ ​s​p​e​e​d​ ​m​u​s​t​ ​b​e​ ​o​n​e​ ​o​f​ ​t​h​e​ ​f​i​v​e​ ​s​p​e​e​d​s​
 ​ ​ ​ ​e​n​u​m​ ​B​l​e​n​d​e​r​S​p​e​e​d​ ​s​p​e​e​d​;​
}​

/​/​ ​s​e​t​S​p​e​e​d​:​ ​e​x​p​e​c​t​s​ ​o​n​e​ ​o​f​ ​t​h​e​ ​f​i​v​e​ ​s​p​e​e​d​s​
-​ ​(​v​o​i​d​)​s​e​t​S​p​e​e​d​:​(​e​n​u​m​ ​B​l​e​n​d​e​r​S​p​e​e​d​)​x​;​
@​e​n​d​

Developers get tired of typing enum BlenderSpeed, so they often use typedef to create a shorthand for it:

t​y​p​e​d​e​f​ ​e​n​u​m​ ​ ​{​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​S​t​i​r​ ​=​ ​1​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​C​h​o​p​ ​=​ ​2​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​L​i​q​u​i​f​y​ ​=​ ​5​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​P​u​l​s​e​ ​=​ ​9​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​I​c​e​C​r​u​s​h​ ​=​ ​1​5​
}​ ​B​l​e​n​d​e​r​S​p​e​e​d​;​

@​i​n​t​e​r​f​a​c​e​ ​B​l​e​n​d​e​r​ ​:​ ​N​S​O​b​j​e​c​t​
{​
 ​ ​ ​ ​/​/​ ​s​p​e​e​d​ ​m​u​s​t​ ​b​e​ ​o​n​e​ ​o​f​ ​t​h​e​ ​f​i​v​e​ ​s​p​e​e​d​s​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​ ​s​p​e​e​d​;​
}​

/​/​ ​s​e​t​S​p​e​e​d​:​ ​e​x​p​e​c​t​s​ ​o​n​e​ ​o​f​ ​t​h​e​ ​f​i​v​e​ ​s​p​e​e​d​s​
-​ ​(​v​o​i​d​)​s​e​t​S​p​e​e​d​:​(​B​l​e​n​d​e​r​S​p​e​e​d​)​x​;​
@​e​n​d​

Often you won’t care what numbers the five speeds represent – only that they are different from each other. You can leave out the values, and the compiler will make up values for you:

t​y​p​e​d​e​f​ ​e​n​u​m​ ​ ​{​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​S​t​i​r​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​C​h​o​p​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​L​i​q​u​i​f​y​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​P​u​l​s​e​,​
 ​ ​ ​ ​B​l​e​n​d​e​r​S​p​e​e​d​I​c​e​C​r​u​s​h​
}​ ​B​l​e​n​d​e​r​S​p​e​e​d​;​
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset