Learning Objective-C would be straightforward for anyone exposed to other languages, if one only wanted to learn Objective-C. You have your basic “C” data types, you have “objects.”
Further in, you have a library of “Foundation” objects that handle numbers, strings, and arrays. This is part of the standard “GNU” distribution and is not Mac-specific. The Root object is of the type “NSObject”
Even Further in, you have the Application Kit frameworks that handle UI elements and their needed features for programming on the Mac (pasting, etc.). “Cocoa” includes both the Foundation and the Application Kit frameworks.
What I needed was a simple, clear-cut rule on when to use pointer nomenclature.
In C-based (and other statically typed) languages, you have to tell the program what kind of information is stored by a variable. So:
int myInteger;
myInteger = 1;
tells the computer that there will be a variable named “myInteger” used to access or manipulate data, to set aside room for that variable, that the variable will be an integer, and sets it to “1.” They can easily be combined into one statement:
int myInteger = 1;
Now, let’s look at objects. First of all, Objective-C, like Python and other object-oriented languages, refers to objects instead of accessing them directly, and so when you define a new variable for an object, you define it as a pointer.
MyClass *myObject;
myObject = [MyClass alloc];
myObject = [myObject init];
This block of text creates a variable called “myString” that is a pointer to an object of the “MyClass” class. The second line calls the classes factory method to allocate the space for the class and create the basic structure of the object. The last line tells the object to initialize itself with any starting information needed so it can be used and referenced.
Why the curly braces? That requires a detour. Like all object oriented languages, objects have methods. For example, “car” objects have “drive” methods that do something when the car is driven. In Objective-C, you call these methods with the following syntax:
[object methodname]
so when I type:
myObject = [myObject init];
I am telling the “myObject” object to run its “init” method, and to assign the object it returns back to “myObject”.
Also – name conventions. In Objective-C, Class, method, and variable names are written out in “camel case,” where instead of using underscores or other characters, descriptive names are put together with first letters capitalized. The very first letter of class names themselves are capitalized, while all other method and variable names, the first letter is lower case. Thus:
myObject = [MyClass alloc];
actually tells the object for the core class to create an instance of itself, and assign it to “myObject,” while:
myObject = [myObject init];
tells the actual object “myObject” to initialize itself, and repoint to its new self when done.
Also, messages can be nested. Since “alloc” returns a valid object, we don’t need separate lines. Instead, we can write:
MyClass *myObject = [[MyClass alloc] init];
Since [MyClass alloc] returns a valid instance of MyClass, it can then be passed a message to initialize itself (via “init”) before handing itself over to our new variable. This one-line methodology is the way you will almost universally see a new class object defined and created.
What about arguments? Arguments are delineated by colons. So, an init with one value passed in would look like:
MyClass *myObject = [[MyClass alloc] initWithArgument: argumentOne];
Simple enough for just one argument (I added italics to make it easier to tell which is which). “initWithArgument:” is the method, and “argumentOne” is the first value passed in. When dealing with multiple arguments, it can appear confusing. Each additional argument gets an additional label and colon. So, a message to implement a method with multiple arguments would look like:
[myObject doSomethingWith: firstArgument andWith: secondArgument andAlso: thirdArgument];
On one hand, this is almost completely different from anything you see in other languages – it reads almost like a normal sentence. That said, it allows you to create very descriptive method names that tell you exacly what it does, and what each value is needed for.
Also, the arguments can be standard “C” datatypes like integers, and they can also be other objects. As a result, if an argument for a method is an object, any method that returns the required type of object can be used as a parameter:
[myObject doSomethingWithObject: [myOtherObject returnAnObjectAsParameter] ];
So, nesting works both for the object being passed a message, as well as for any objects being used as the parameters of that message.
All of the data types we’ve dealt with are statically assigned, yet, Objective-C is a “dynamically” typed language. This is because of one other data type I haven’t discussed yet: “id”. The “id” data type is a “generic” object pointer that can point to any type of object. It is most commonly seen when receiving actions from UI elements, or in other methods where the type of data is unknown, other than being an object.
The “id” type also doesn’t use the pointer notation. As a result, unlike the examples we’ve seen above, a variable for an “id” is declared without the asterix:
id myIdObject;
Unlike static typing, any object of the “id” type can receive any message, and as long as the appropriate method exists, will do whatever the method instructs it to do. This is great for flexibility, but the downside is that you also can’t use key-value coded parameters, or any other convenience that relies on knowing the class type. You also don’t get error-checking when compiling the program. For the sake of speed and compiler error-checking, when possible, use statically assigned data types. You can often use a parent “super” class to allow some flexibility without sacrificing all of the error checking.
For some more good information on naming and programming conventions, you can look at part 1 and part 2 of the article “Cocoa Style for Objective-C.”