[back]   [TOC]   [forward]


Chapter 6
Plugin Registration
iSimplePlug Documentation


Plugin registration happens more or less automatically if the plugin is installed in the correct place. However, there are several methods that should be implemented by any plugin. They are commands, pluginName, pluginVersionString, and pluginRegistered.

The commands Method

The commands method is relatively straight forward. It returns an NSArray of all the commands the plugin implements, stored as NSStrings. It is used by iTonamaton to register the commands in its database, assign them identification numbers, and then properly recognize them when received from IRC. Therefore it is important that this method always return a complete list of implemented commands at all times.

Fortunately, in our case, we have already constructed the required NSArray in the initWithOwner: method, and assigned it to the instance variable commandNameArray. Therefore, we can just return this array from this method. (For those new programmers who are curious, this array should not be autoreleased, since it wasn't alloced, retained, or copied in this method.)

Thus the code for this method is simply as follows:

- (NSArray *)commands
{
    return commandNameArray;
}

The pluginName Method

The pluginName method returns an NSString that contains the name of the plugin. This name is used whenever a human readable version of the plugin's name is needed. For example, the name returned by this method is used by iTonamaton, along with the result of pluginVersionString, to make a version string that can be displayed using a variation of the "!version" command.

The code for this method is as follows:

- (NSString *)pluginName
{
    return @"iSimplePlugin";
}

The pluginVersionString Method

The pluginVersionString method returns an NSString that contains human readable versioning information that can be displayed by iTonamaton. It should not have the name of the plugin anywhere within it, as the plugin name is seperately accessed through the pluginName method.

Although the version string can be anything you want (a date, a number, a tag), I have chosen to use the CVS revision number of the source file for the version information. This makes sense in this case because the plugin is stored in the iTonamaton CVS archive, and is only one source file. More complicated plugins may want to have an alternate method of version string generation. (For example, iTonamaton uses a perl script to generate a build string each time the program is compiled.

The code for the pluginVersionString method is as follows:

- (NSString *)pluginVersionString
{
    return @"CVS Revision $Revision$";
}

The pluginRegistered Method

The pluginRegistered method in iTonamaton is analogous to the awakeFromNib method in Cocoa GUI programming. It is called when the plugin has been properly loaded and registered, and the plugin must finish setting itself up for use in iTonamaton.

In the iSimplePlug plugin's version of this method, we need to cache the values of the command ID numbers and register the plugin to recieve notifications that commands were received by iTonamaton. This is accomplished with the following code:

- (void)pluginRegistered
{
    // Cache the command IDs.
    unsigned i;
    for( i=0; i<[commandNameArray count]; i++ )
        commandIDArray[i] =
        	[self identifierForCommand:[commandNameArray objectAtIndex:i]];
    
    // Register to be notified of command events.
    [[[self owner] eventCenter]
            addObserver:self
            selector:@selector(processCommand:)
            name:ITCommandReceivedNotification
            object:[self owner]];
}

The first part of this method is a for loop that loops over each element in the NSArray of command strings, fetches the identifier for the command, and then sets the corresponding element in the ID array to the command's numeric value.

Let's look at that in more detail. [commandNameArray objectAtIndex:i] fetches the ith command in the command array, where i starts at zero for the first command, and runs to N-1 for the last command (where N is the number of commands in the array). This command string is then passed into the ITPlugin convenience method identifierForCommand. This method takes the command name in the form of an NSString, and returns the unsigned identifier corresponding to it in the command registry. The value returned from this is then stored in the corresponding element of the commandIDArray array of unsigned values.

The second part of this method is actually a just two combined method calls, with two extra calls to [self owner] woven in. The eventCenter method gets the NSNotificationCenter that iTonamaton uses to communicate events to the plugins. The second call, addObserver:selector:name:object: then tells the notification center to notify the plugin when a command needs to be processed.

The first argument, addObserver, merely tells the notification center that the plugin is the object registering to observe notifications (that is, listen to events). The name argument tells the notification center to filter out every notification except ones that have to do with iTonamaton having recieved a command from IRC. The object argument then tells the notification center to filter out every notification that isn't sent from the plugins owner (which is the ITonamaton object set in the initWithOwner method). Lastely, the selector argument tells the notification center to send any notifications that are left to the plugin's processCommand: method.

An obervant reader might ask why I insist on using [self owner] instead of simply owner in the above code. I mean, owner is an instance variable of ITPlugin, and it is accessable from the SimplePlug class. The answer is that if iTonamaton were to change its internal implementation of the ITPlugin class so that the owner instance variable no longer worked the same, all the plugins that directly accessed this instance variable would break. However, a programmer that observes good modularization rules and accesses superclass instance variables through the superclass' accessor methods, will not encounter such a problem. (Note that this principle holds true in most cases in virtually all object oriented languages.)


[back]   [TOC]   [forward]
Last Modified: $Date: 2003/12/16 01:29:33 $ by $Author: paploo $