Objective-C Basics
The first thing you need is to set up your build environment. For most of these examples, you can use any OS that supports GCC. If you're running on Mac OS X, install the development tools and you're done. For Ubuntu or Fedora, install the appropriate compiler packages and any dependencies. On Ubuntu, the build-essential package works well. For Fedora, install the Developer Tools grouplist and the gcc-objc package.
You'll also need the Foundation framework libraries and headers. Ubuntu keeps these in the libgnustep-base and libgnustep-base-dev packages. Fedora calls it gnustep-base-devel. Fedora also requires the gcc-objc package on top of the Developers Tools grouplist.
If you already know 'C', then you have a good basis for Objective-C. As the name implies, Objective-C is an extension of C, much like C++ is. Here is our first example source file example1.m:
#include
int main(int argc, char *argv[]) {
printf("Hello, World!\n");
}
Looks rather like a standard C program, doesn't it? Compile it with:
gcc example1.m -o example1
Valid Objective-C this may be, it employs a grand total of zero Objective-C features, like #import or the NSString class. It is, despite the .m extension, not really an Objective-C program. Here's the point: Anything you can do in C you can do in Objective-C.
Let's add in some Objective-C features and see what we get. We'll start with #import. How many times have you added the following around your header files?
#ifndef _FOO_H_
#define _FOO_H_
/* Stuff */
#endif
The purpose of this is to make sure the compiler includes any header file once and only once. Objective-C finally made that a built-in feature with the #import directive. Our first edit to example1.m is to replace the #include with #import.
One directive does not an Objective-C program make, said the green muppet. If we want a real Objective-C program, we need to use something gooey, crunchy, peanut-buttery. Something from Objective-C's base library of classes called the Foundation Framework would do nicely.
Converting the char* string to an NSString is not as simple as changing the type. That's because a 'C' char is 8 bits wide, but NSString is an Objective-C object descended from NSObject built to manage a Unicode version of the string. A footnote in the Kochan book implies that the internal representation is UTF-16. In reality, it doesn't matter because the NSString class internals handle all of the string manipulation for you.
To use the NSString class, we need to include the Foundation library header Foundation/Foundation.h, declare the NSString and initialize it, then print it out to the screen. When you're done, the code should look something like the code segment below. Go ahead and type it all in, then we'll talk about what we just did.
#import
#import
int main(int argc, char *argv[]) {
NSString *hello = @"hello, world!\n";
printf([hello cString]);
}
What are we doing here? The #import pulls in all of the Foundation Framework classes. That particular header file is filled with lines like #import . Every framework should have a header file that pulls in all the header files in the framework, typically named after the framework.
The declaration of hello says it is an NSString object, with the starting value of @"hello, world.\n". The @"..." isn't a typo, it's how you tell the compiler you're declaring a static Objective-C string.
Finally, the [hello cString] sends the "cString" message to our NSString class to convert the NSString back to the 'C' style string that printf is expecting. Ready to build it?
~/objc/example1$ gcc example1.m -o example1
example1.m:2:34: error: Foundation/Foundation.h: No such file or directory
example1.m: In function 'main':
example1.m:5: error: 'NSString' undeclared (first use in this function)
example1.m:5: error: (Each undeclared identifier is reported only once
example1.m:5: error: for each function it appears in.)
example1.m:5: error: 'hello' undeclared (first use in this function)
example1.m:5: error: cannot find interface declaration for 'NXConstantString'
example1.m:6: warning: format not a string literal and no format arguments
Well, that didn't work. The compiler doesn't know where to find the Foundation framework, and because of that it doesn't know about NSString. The "'hello' undeclared' makes sense, but what is this NXConstantString error?
Objective-C defines different types of strings. The NSString class only handles the most basic kind of strings: immutable strings. If you want to be able to create a string object that you can append or remove bits from, you either need to create new NSString objects each time or create an NSMutableString object. NSMutableString is a subclass of NSString, so anywhere you would use the NSString class, you can also use an NSMutableString.
NXConstantString is another special kind of string that is pre-defined in the language. The @"..." construct tells the compiler you want an constant string, and it initializes the full object in the executable. For some technical compiler reasons, the NXConstantString is a separate subclass of NSString, not an NSString object itself. Because it is a subclass, it can be assigned as an NSString object, but never an NSMutableString.
We can fix the headers with a -I /usr/lib/GNUStep. Try it again:
~/objc/example1$ gcc example1.m -o example1 -I /usr/include/GNUstep/
example1.m: In function 'main':
example1.m:5: error: cannot find interface declaration for 'NXConstantString'
example1.m:6: warning: format not a string literal and no format arguments
Better, but still not working. The problem is the NXConstantString is really an NSConstantString. (Why such a fundamental thing doesn't Just Work™, I couldn't tell you.) We can fix this by explicitly telling the compiler to use the right class:
~/objc/example1$ gcc example1.m -o example1 -I /usr/include/GNUstep/ -fconstant-string-class=NSConstantString
example1.m: In function 'main':
example1.m:6: warning: format not a string literal and no format arguments
/tmp/ccc8G04z.o: In function `main':
example1.m:(.text+0x29): undefined reference to `objc_msg_lookup'
/tmp/ccc8G04z.o: In function `__objc_gnu_init':
example1.m:(.text+0x5d): undefined reference to `__objc_exec_class'
/tmp/ccc8G04z.o:(.data+0x78): undefined reference to `__objc_class_name_NSConstantString'
collect2: ld returned 1 exit status
Still not working, but at least we have new errors.
Remember before when I said that Objective-C was an extension of C? Those extensions are partially library-based. The [hello cString] actually translates to a call to objc_msg_send. This function lives in libobjc.so, and is heavily optimized. When I talked about sending a message to the NSString object above, I wasn't kidding. It's not just a fancy way of saying "call a function," it is really a different mechanism. This message sending mechanism is necessary for Objective-C to effect dynamic typing.
The compiler also needs to know where to find __objc_class_name_NSConstantString (a might bit easier to read than C++'s name mangling!). That lives in libgnustep_base.so.
Let's add the libraries and see if it works.
~/objc/example1$ gcc example1.m -o example1 -I /usr/include/GNUstep/ -fconstant-string-class=NSConstantString -lobjc -lgnustep-base
example1.m: In function 'main':
example1.m:6: warning: format not a string literal and no format arguments
Success! We have created a Hello, World application in Objective-C. Not exciting, but you've learned some basic Objective-C, you've worked your way though several compiler and linker issues, and you've had a peek into the internals of the language.
On your own, try replacing the printf with:
NSLog(hello);
NSLog will be your new best friend once you get into iPhone development. Now is a great time to get familiar with him.
Next up: Our own Objective-C class!
First published at Sentai Digital
- John Franklin's blog
- Login or register to post comments
-