- •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
Challenge
if (fido != nil) {
[fido goGetTheNewspaper];
}
When Objective-C was designed, it was decided that sending a message to nil would be OK; it just wouldn’t do anything at all. Thus, this code is completely legal:
Dog *fido = nil;
[fido goGetTheNewspaper];
Important thing #1: If you are sending messages and nothing is happening, make sure you aren’t sending messages to a pointer that has been set to nil.
Important thing #2: If you send a message to nil, the return value doesn’t mean anything.
Dog *fido = nil;
Newspaper *daily = [fido goGetTheNewspaper];
In this case, daily will be zero. (In general, if you expect a number or a pointer as a result, sending a message to nil will return zero. However, for other types like structs, you will get strange and unexpected return values.)
Challenge
On your Mac, there is a class NSTimeZone. Among its many methods are the class method systemTimeZone, which returns the time zone of your computer (as an instance of NSTimeZone), and the instance method isDaylightSavingTime, which returns YES if the time zone is currently in daylight savings time.
Write a Foundation Command Line Tool that tells you if it is currently daylight savings time.
83
This page intentionally left blank
14
NSString
NSString is another class like NSDate. Instances of NSString hold character strings. In code, you can create a literal instance of NSString like this;
NSString *lament = @"Why me!?";
In your TimeAfterTime project, you typed in this code:
NSLog(@"The date is %@", now);
NSLog() is an Objective-C function (not a method!) that works a lot like printf(). In NSLog(), however, the format string is actually an instance of NSString.
Instances of NSString can also be created programmatically using the stringWithFormat: class method:
NSString *x = [NSString stringWithFormat:@"The best number is %d", 5];
To get the number of characters in a string, you use the length method:
NSUInteger charCount = [x length];
And you check to see if two strings are equal using the isEqual: method:
if ([lament isEqual:x])
NSLog(@"%@ and %@ are equal", lament, x);
The C language also has a character string construct. Here’s what the preceding string examples would look like in C:
char *lament = "Why me!?"; char *x;
asprintf(&x, "The best number is %d", 5); size_t charCount = strlen(x);
if (strcmp(lament, x) == 0)
printf("%s and %s are equal\n", lament, x); free(x);
We will discuss C strings in Chapter 34. But whenever you have a choice, use NSString objects instead of C strings. The NSString class has many methods designed to make your life easier. Plus, NSString (which is based on the UNICODE standard) is exceedingly good at holding text from any language on the planet. Strange characters? No problem. Text that reads from right to left? No worries.
85
Chapter 14 NSString
Challenge
There is a class called NSHost which has information about your computer. To get an instance of NSHost, you can use the NSHost class method currentHost. This method returns a pointer to an NSHost object:
+ (NSHost *)currentHost
To get the localized name of your computer, you can use the NSHost instance method localizedName that returns a pointer to an NSString object:
- (NSString *)localizedName
Write a Foundation Command Line Tool that prints out the name of your computer. (This sometimes takes a surprisingly long time to run.)
86
15
NSArray
Like NSString, NSArray is another class that Objective-C programmers use a lot. An instance of NSArray holds a list of pointers to other objects. For example, let’s say you want to make a list of three NSDate objects and then go through the list and print each date.
Create a new project : a Foundation Command Line Tool called DateList. Open main.m and change the main() function:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
//Create three NSDate objects NSDate *now = [NSDate date];
NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0]; NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0];
//Create an array containing all three (nil terminates the list)
NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday, nil];
// |
How many dates |
are there? |
NSLog(@"There are |
%lu dates", [dateList count]); |
|
// |
Print a couple |
|
NSLog(@"The first |
date is %@", [dateList objectAtIndex:0]); |
|
NSLog(@"The third |
date is %@", [dateList objectAtIndex:2]); |
|
} |
|
|
return |
0; |
|
}
NSArray has two methods, shown in this example, that you will use all the time:
•count returns the number of items in an array
•objectAtIndex: returns the pointer that the array has stored at the index specified by the argument.
Arrays are ordered, and you access an item in the array by its index. Arrays are zero-based: the first item is stored at index 0, the second item is stored at index 1, and so on. Thus, if the count method says there are 100 items in the array, you can use objectAtIndex: to ask for the objects at indices 0 to 99.
87
Chapter 15 NSArray
Figure 15.1 is an object diagram of your program. Notice that the instance of NSArray has pointers to the NSDate objects.
Figure 15.1 Object diagram for DateList
Thus, if you want to loop and process each item in the array (or “iterate over the array”), you can create a for-loop. Edit main.m:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
//Create three NSDate objects NSDate *now = [NSDate date];
NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0]; NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0];
//Create an array containing all three (nil terminates the list)
NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday, nil];
NSUInteger dateCount = [dateList count]; for (int i = 0; i < dateCount; i++) {
NSDate *d = [dateList objectAtIndex:i]; NSLog(@"Here is a date: %@", d);
}
}
return 0;
}
Programmers do this so often that they made a special addition to the for-loop for iterating over arrays. Edit the code to use this mechanism:
88