- •C and Objective-C
- •How this book works
- •How the life of a programmer works
- •Installing Apple’s developer tools
- •Getting started with Xcode
- •Where do I start writing code?
- •How do I run my program?
- •So what is a program?
- •Don’t stop
- •Types
- •A program with variables
- •Challenge
- •Boolean variables
- •When should I use a function?
- •How do I write and use a function?
- •How functions work together
- •Local variables, frames, and the stack
- •Recursion
- •Looking at the frames in the debugger
- •return
- •Global and static variables
- •Challenge
- •printf()
- •Integer operations
- •Integer division
- •Operator shorthand
- •Floating-point numbers
- •Tokens for displaying floating-point numbers
- •The while loop
- •The for loop
- •break
- •continue
- •The do-while loop
- •Challenge
- •Getting addresses
- •Storing addresses in pointers
- •Getting the data at an address
- •How many bytes?
- •NULL
- •Stylish pointer declarations
- •Challenges
- •Writing pass-by-reference functions
- •Avoid dereferencing NULL
- •Creating and using your first object
- •Message anatomy
- •Objects in memory
- •Challenge
- •Nesting message sends
- •Multiple arguments
- •Sending messages to nil
- •Challenge
- •Challenge
- •NSMutableArray
- •Reference pages
- •Quick Help
- •Other options and resources
- •Accessor methods
- •Dot notation
- •Properties
- •self
- •Multiple files
- •Challenge
- •Overriding methods
- •super
- •Challenge
- •Object ownership and ARC
- •Creating the Asset class
- •Adding a to-many relationship to Employee
- •Challenge
- •Retain cycles
- •Weak references
- •Zeroing of weak references
- •For the More Curious: Manual reference counting and ARC History
- •Retain count rules
- •NSArray/NSMutableArray
- •Immutable objects
- •Sorting
- •Filtering
- •NSSet/NSMutableSet
- •NSDictionary/NSMutableDictionary
- •Preprocessor directives
- •#include and #import
- •#define
- •Global variables
- •enum
- •#define vs global variables
- •Writing an NSString to a file
- •Reading files with NSString
- •Writing an NSData object to a file
- •Reading an NSData from a file
- •Target-action
- •Helper objects
- •Notifications
- •Which to use?
- •Callbacks and object ownership
- •Challenge
- •Getting started with iTahDoodle
- •BNRAppDelegate
- •Adding a C helper function
- •Objects in iTahDoodle
- •Model-View-Controller
- •The application delegate
- •Setting up views
- •Running on the iOS simulator
- •Wiring up the table view
- •Adding new tasks
- •Saving task data
- •For the More Curious: What about main()?
- •Edit BNRDocument.h
- •A look at Interface Builder
- •Edit BNRDocument.xib
- •Making connections
- •Revisiting MVC
- •Edit BNRDocument.m
- •Writing init methods
- •A basic init method
- •Using accessors
- •init methods that take arguments
- •Deadly init methods
- •Property attributes
- •Mutability
- •Lifetime specifiers
- •copy
- •More about copying
- •Advice on atomic vs. nonatomic
- •Key-value coding
- •Non-object types
- •Defining blocks
- •Using blocks
- •Declaring a block variable
- •Assigning a block
- •Passing in a block
- •typedef
- •Return values
- •Memory management
- •The block-based future
- •Challenges
- •Anonymous block
- •NSNotificationCenter
- •Bitwise-OR
- •Bitwise-AND
- •Other bitwise operators
- •Exclusive OR
- •Complement
- •Left-shift
- •Right-shift
- •Using enum to define bit masks
- •More bytes
- •Challenge
- •char
- •char *
- •String literals
- •Converting to and from NSString
- •Next Steps
- •Index
Global variables
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSLog(@"\u03c0 is %f", M_PI);
NSLog(@"%d is larger", MAX(10, 12));
}
return 0;
}
MAX is not a function; it is a #define. The most basic C version of MAX is:
#define MAX(A,B) |
((A) > (B) ? (A) : (B)) |
So, by the time the compiler saw the line you just added, it looked like this:
NSLog(@"%d is larger", ((10) > (12) ? (10) : (12)));
When you use #define to do function-like stuff instead of simply substituting a value,you are creating a macro.
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:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSLog(@"\u03c0 is %f", M_PI);
NSLog(@"%d is larger", MAX(10, 12));
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:@"currency"];
NSLog(@"Money is %@", currency);
}
return 0;
}
Build and run it. Depending on where you are, you should see something like
Money is USD
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
147
Chapter 22 Constants
properly for a global variable, but not for the string @"currency". Change your code to use the constant:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSLog(@"\u03c0 is %f", M_PI);
NSLog(@"%d is larger", MAX(10, 12));
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:NSLocaleCurrencyCode];
NSLog(@"Money is %@", currency);
}
return 0;
}
When the class NSLocale was written, this global variable appeared in two places. In NSLocale.h, the variable was declared something like this:
extern NSString const *NSLocaleCurrencyCode;
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:
NSString const *NSLocaleCurrencyCode = @"currency";
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:
enum BlenderSpeed { BlenderSpeedStir = 1, BlenderSpeedChop = 2, BlenderSpeedLiquify = 5, BlenderSpeedPulse = 9, BlenderSpeedIceCrush = 15
};
@interface Blender : NSObject
{
// speed must be one of the five speeds enum BlenderSpeed speed;
}
// setSpeed: expects one of the five speeds - (void)setSpeed:(enum BlenderSpeed)x;
@end
Developers get tired of typing enum BlenderSpeed, so they often use typedef to create a shorthand for it:
148