Just like C, Objective- C uses header files to hold the declarations of elements such as
structs, symbolic constants, and function prototypes. In C, you use the #include statement
to inform the compiler that it should consult a header file for some definitions. You can
use #include in Objective- C programs for the same purpose, but you probably never will.
Instead, you’ll use #import, like this:
#import
#import is a feature provided by the GCC compiler, which is what Xcode uses when you’re
compiling Objective- C, C, and C++ programs. #import guarantees that a header file will be
included only once, no matter how many times the #import directive is actually seen for
that file.
NSLog()
#import
int main (int argc, const char * argv[])
{
const char *words[4]
= { "Joe- Bob \"Handyman\" Brown",
"Jacksonville \"Sly\" Murphy",
"Shinara Bain",
"George \"Guitar\" Books" };
int wordCount = 4;
int i;
for (i = 0; i < wordCount; i++) {
NSLog (@"%s is %d characters long",
words[i], strlen(words[i]));
}
return (0);
} // main
Joe-Bob "Handyman" Brown is 24 characters long
Jacksonville "Sly" Murphy is 25 characters long
Shinara Bain is 12 characters long
George "Guitar" Books is 21 characters long
#import
int main (int argc, const char * argv[])
{
FILE *wordFile = fopen ("/tmp/words.txt", "r");
char word[100];
while (fgets(word, 100, wordFile)) {
// strip off the trailing \n
word[strlen(word) - 1] = ‘\0’;
NSLog (@"%s is %d characters long",
word, strlen(word));
}
fclose (wordFile);
return (0);
} // main
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;
typedef struct {
ShapeType type;
ShapeColor fillColor;
ShapeRect bounds;
} Shape;
typedef struct {
int x, y, width, height;
} ShapeRect;
ShapeRect rect0 = { 0, 0, 10, 30 };
int main (int argc, const char * argv[])
{
id shapes[3];
ShapeRect rect0 = { 0, 0, 10, 30 };
shapes[0] = [Circle new];
[shapes[0] setBounds: rect0];
[shapes[0] setFillColor: kRedColor];
ShapeRect rect1 = { 30, 40, 50, 60 };
shapes[1] = [Rectangle new];
[shapes[1] setBounds: rect1];
[shapes[1] setFillColor: kGreenColor];
ShapeRect rect2 = { 15, 19, 37, 29 };
shapes[2] = [OblateSphereoid new];
[shapes[2] setBounds: rect2];
[shapes[2] setFillColor: kBlueColor];
drawShapes (shapes, 3);
return (0);
} // main
standard definition
@interface Shape : NSObject
{
ShapeColor fillColor;
ShapeRect bounds;
}
- (void) setFillColor: (ShapeColor) fillColor;
- (void) setBounds: (ShapeRect) bounds;
- (void) draw;
@end // Shape
In Objective- C, you compose by including pointers to objects as instance
variables. So, our virtual unicycle would have a pointer to a Pedal object and
a pointer to a Tire object and would look something like this:
@interface Car : NSObject
{
Engine *engine;
Tire *tires[4];
}
- (void) print;
@end // Car
@implementation Car
- (id) init
{
if (self = [super init]) {
engine = [Engine new];
tires[0] = [Tire new];
tires[1] = [Tire new];
tires[2] = [Tire new];
tires[3] = [Tire new];
}
return (self);
} // init
This line of code in the init method looks a little odd:
if (self = [super init]) {We’ll explain what’s happening here. You need to call [super init] so that the superclass (NSObject, in this case) can do any one- time initialization that it needs to do. The init method returns a value (of type id, a generic object pointer) representing the object that was initialized.
Assigning the result of [super init] back to self is a standard Objective- C convention. We do this in case the superclass, as part of its initialization work, returns a different object than the one originally created. We’ll explore this in depth in a later chapter when we cover init methods in more detail, so for now, please just nod and smile over this line of code, and we’ll move on.
Accessor Methods
@interface Car : NSObject
{
Engine *engine;
Tire *tires[4];
}
- (Engine *) engine;
- (void) setEngine: (Engine *) newEngine;
- (Tire *) tireAtIndex: (int) index;
- (void) setTire: (Tire *) tire
atIndex: (int) index;
- (void) print;
@end // Car
@class sets up a forward reference. This is a way to tell the compiler, “Trust me; you’ll learn eventually
what this class is, but for now, this is all you need to know.”
@class is also useful if you have a circular dependency. That is, class A uses class B, and class B uses
class A. If you try having each class #import the other, you’ll end up with compilation errors. But if you
use @class B in A.h and @class A in B.h, the two classes can refer to each other happily.
hanging the Company Name
//
// TapDance.h
// Groovilicous
//
// Created by markd on 7/25/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions➥
'{"ORGANIZATIONNAME" = "Length-O- Words.com";}'
NSRange range;
range.location = 17;
range.length = 4;
NSRange range = { 17, 4 };
NSString
unsigned int length = [height length];
or in expressions like so:
if ([height length] > 35) {
NSLog (@"wow, you're really tall!");
}
NSString *thing1 = @"hello 5";
NSString *thing2;
thing2 = [NSString stringWithFormat: @"hello %d", 5];
if ([thing1 isEqualToString: thing2]) {
NSLog (@"The strings are the same!");
}
is different from
if (thing1 == thing2) {
NSLog (@"They are the same object!");
}
Similarly, [@"zoinks" compare: @"jinkies"] would return NSOrderedDescending. And,
as you’d expect, [@"fnord" compare: @"fnord"] would return NSOrderedSame.
if ([thing1 compare: thing2
options: NSCaseInsensitiveSearch
| NSNumericSearch]
== NSOrderedSame) {
NSLog (@"They match!");
}
if ([fileName hasSuffix: @".mov") {
// this is a movie
}
To split an NSArray, use -componentsSeparatedByString:, like this:
NSString *string = @"oop:ack:bork:greeble:ponies";
NSArray *chunks = [string componentsSeparatedByString: @":"];
And to join an NSArray and create a string of its contents, use componentsJoinedByString::
string = [chunks componentsJoinedByString: @" :- ) "];
The preceding line would produce an NSString with the contents “oop :- ) ack :- ) bork :- ) greeble :- ) ponies”.
Mutability
Programmers coming from Java should feel at home with this distinction. NSString behaves like the
java String class, and NSMutableString is like Java’s StringBuffer class.
NSMutableString *string;
string = [NSMutableString stringWithCapacity: 50];
[string appendString: @"Hello there "];
[string appendFormat: @"human %d!", 39];
NSArray
NSArray *array;
array = [NSArray arrayWithObjects:
@"one", @"two", @"three", nil];
int i;
for (i = 0; i < [array count]; i++) {
NSLog (@"index %d has %@.",
i, [array objectAtIndex: i]);
}
NSMutableArray *array;
array = [NSMutableArray arrayWithCapacity: 17];
Add objects to the end of the array by using addObject:.
- (void) addObject: (id) anObject;
You can add four tires to an array with a loop like this:
for (i = 0; i < 4; i++) {
Tire *tire = [Tire new];
[array addObject: tire];
}
[array removeObjectAtIndex: 1];
Enumeration
NSEnumerator *enumerator;
enumerator = [array objectEnumerator];
id thingie;
while (thingie = [enumerator nextObject]) {
NSLog (@"I found %@", thingie);
}
Tire *t1 = [Tire new];
Tire *t2 = [Tire new];
Tire *t3 = [Tire new];
Tire *t4 = [Tire new];
NSDictionary *tires;
tires = [NSDictionary dictionaryWithObjectsAndKeys:
t1, @"front- left", t2, @"front- right",
t3, @"back- left", t4, @"back- right", nil];
Tire *tire = [tires objectForKey: @"back- right"];
NSMutableDictionary *tires;
tires = [NSMutableDictionary dictionary];
[tires setObject: t1 forKey: @"front- left"];
[tires setObject: t2 forKey: @"front- right"];
[tires setObject: t3 forKey: @"back- left"];
[tires setObject: t4 forKey: @"back- right"];
NSValue, NSNull
NSNumber is actually a subclass of NSValue, which wraps arbitrary values. You can use
NSValue to put structures into NSArrays and NSDictionaries. Create a new NSValue using
this class method:
NSValue *value;
value = [NSValue valueWithBytes: &rect
objCType: @encode(NSRect)];
[array addObject: value];
[contact setObject: [NSNull null]
forKey: @"home fax machine"];
id homefax;
homefax = [contact objectForKey: @"home fax machine"];
if (homefax == [NSNull null]) {
// ... no fax machine. rats.
}
NSFileManager
NSFileManager *manager;
manager = [NSFileManager defaultManager];
NSString *home;
home = [@"~" stringByExpandingTildeInPath];
NSDirectoryEnumerator *direnum;
direnum = [manager enumeratorAtPath: home];
NSMutableArray *files;
files = [NSMutableArray arrayWithCapacity: 42];
NSString *filename;
while (filename = [direnum nextObject]) {
if ([[filename pathExtension]
isEqualTo: @"jpg"]) {
[files addObject: filename];
}
}
NSEnumerator *fileenum;
fileenum = [files objectEnumerator];
while (filename = [fileenum nextObject]) {
NSLog (@"%@", filename);
}
Hiç yorum yok:
Yorum Gönder