startuprob
startuprob

Reputation: 1915

Question with Apple's Cocoa Documentation

I am slowly but surely working through Apple's dense documentation, but I really have to ask a question. The following example code is given:

#import "MonthArray.h"

@implementation MonthArray

static MonthArray *sharedMonthArray = nil;
static NSString *months[] = { @"January", @"February", @"March",
    @"April", @"May", @"June", @"July", @"August", @"September",
    @"October", @"November", @"December" };

+ monthArray
{
    if (!sharedMonthArray) {
        sharedMonthArray = [[MonthArray alloc] init];
    }
    return sharedMonthArray;
}

- (unsigned)count
{
 return 12;
}

- objectAtIndex:(unsigned)index
{
    if (index >= [self count])
        [NSException raise:NSRangeException format:@"***%s: index
            (%d) beyond bounds (%d)", sel_getName(_cmd), index,
            [self count] - 1];
    else
        return months[index];
}

@end

Here are my questions (I apologize for not making multiple threads, but from what I can tell - these are fairly basic.)

  1. What exactly does it mean when it shows +monthArray? I know that the + means that it is a class method, but I don't entirely understand what implications that has. How exactly does it make it different than a normal method?

  2. What is the purpose in this code for the whole sharedMonthArray ivar? I mean, the objectAtIndex: method is pulling from the months' strings, so what's the point?

  3. What is the "self" in the [self count] method? I mean, I understand that it is supposed to be the months, but where do I see that in the program? What makes [self count] count the months and not count the number of MonthArrays?

Sorry if my questions are uber-elementary, I am still learning - thanks in advance for the help.

Upvotes: 1

Views: 127

Answers (3)

danyowdee
danyowdee

Reputation: 4698

First, the class-method is missing a return type — let's fix that:

+ (MonthArray *)monthArray {...}

Now to your first question:
The difference between an instance-method and a class-method is the target, you call it on. Like the name implies, you call a class-method on the class-object. Examples of this are

// call a factory-method of NSArray to create a new array:
NSArray *array = [NSArray arrayWithObject:@"foo"];
// obtain the current notification-center
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
// obtain a singleton
NSApplication *app = [NSApplication sharedApplication];

So there is exactly one object, you can call the method on — in this case, to retrieve the singleton, that is implemented by this class.

With that we come to your second question:
When you call [MonthArray monthArray], you will be returned the only instance of this class that was intended to be created. There must — however — be a way to store that instance somewhere, so that it can be retrieved later. You do this in a static variable (in Java, this would be a class variable). Same goes for the months, which are only needed once.
objectAtIndex:only exists to wrap the raw C-array with a thin Objective-C layer. Remember, that C will happily let you do something like months[42] — only to crash somewhere later because it's pretty unlikely that the thing you'll obtain there, will be an NSString.

Your third question:
self is not the months! It is an instance of MonthsArray and — as this code obviously intends — the only one that should exist (namely, the object stored as sharedMonthsArray). As an instance of MonthArray, it responds to the count selector and will simply return 12 when being sent this message (see implementation of -(unsigned)count). It doesn't count the months: you could change months like this

NSString *months[] = { @"January", @"February", @"March",
@"April", @"May", @"June", @"July", @"August", @"September",
@"October", @"November", @"December", @"Dancing Hippo Month" };

and it would still return 12.

Upvotes: 0

James Eichele
James Eichele

Reputation: 119154

What exactly does it mean when it shows +monthArray? I know that the + means that it is a class method, but I don't entirely understand what implications that has. How exactly does it make it different than a normal method?

Class methods are functions that can be called without providing an instance of the class. In Objective-C, you normally send messages to an instance as follows: [someObject someMethod]; With a class method, you send the message to the class itself: [SomeClass someClassMethod];. Class methods are usually used to do things that are specific to all objects of that particular class, such as creating a new instance (i.e. a factory method) or maintaining/updating a global class variable.

What is the purpose in this code for the whole sharedMonthArray ivar? I mean, the objectAtIndex: method is pulling from the months' strings, so what's the point?

The purpose of sharedMonthArray is to hold a single, common instance of the class. It would be possible to return a new instance every time +monthArray is called, but that could be a waste of memory, since there really only needs to be one. Most Cocoa code uses NSArray objects, and not simple C-style arrays, so this single instance is like a NSArray wrapper to hide that static C-array from the rest of the program by providing a NSArray instance instead. Internally, the C-style array is used because there is no way to create a static constant NSArray object at compile-time.

What is the "self" in the [self count] method? I mean, I understand that it is supposed to be the months, but where do I see that in the program? What makes [self count] count the months and not count the number of MonthArrays?

self is an automatic variable that the Objective-C runtime uses to hold the object which receives a certain message. If you send the message [someObject someMethod];, this will jump to the -someMethod method, and the value of self will be equal to someObject. In this example, self will be whichever instance of MonthArray was sent the -objectAtIndex: message. The call to [self count] will result in the method -count being called, and will return a value of 12, according to the code shown.

I would like to add that the code shown here is fairly unique in the Cocoa world. The only time you would really write something like this is if you were creating your own framework. The majority of Cocoa source code will not use C-style arrays. What was the purpose of this particular example? It is definitely not the kind of code a Cocoa developer will write on a daily basis.

Upvotes: 4

user57368
user57368

Reputation: 5765

This object is implemented as a singleton, meaning that in normal use there will only be one instance. You get a reference to that instance with [MonthArray monthArray], which sends the message +monthArray to the class MonthArray. That method creates the sharedMonthArray if needed, and returns it. Since sharedMonthArray is declared static, it isn't an instance variable - it's a class variable, shared by all instances and accessible to class methods.

-count is simply a message that can be sent to a MonthArray, and it always returns 12, which is the number of months in a year. That message doesn't do any real work. It's more of a getter for a property that isn't explicitly declared.

The occurrences of [self count] are where the MonthArray instance sends a message to itself. In other languages, it might be written as this.count()

Upvotes: 1

Related Questions