s.im.pl oodss:
public chat tutorial [objective-c]

Contents:
Introduction

This example demonstrates how to use the OODSS library in Objective-C. In this tutorial we present the implementation of an iPhone client for the Public Chat Service. This tutorial demonstrates how to use the the Objective-C OODSS client implementation.

Access to the entire ecologylab fundamental Objective-C project source is available through anonymous SVN access (user: anonymous, password: anonymous).
The source for this tutorial is located under in the Xcode project under /Classes/Applications/ChatClientTutorial/Messages

Chat Request

We will first show the implementation of the single request message in the public chat service. ChatRequest is the message that is initially sent from the client to indicate the posting of a new message to the chat service. The ChatRequest message only contains the message being posted, stored as a String instance variable, and passed in XML as an attribute. The code show below was generated automatically with the java CocoaTranslator.

#import "ChatRequest.h"


@implementation ChatRequest


@synthesize message;


+ (void) initialize {

[ChatRequest class];

}


@end

Update Message

We now define the update message that is sent to clients to indicate that another client has posted a message to the chat service. Update messages are messages that are sent from the server to client without being specifically requested. Updates do not require that the client respond, if further action is necessary on the part of the client, then it may initiate a new request. Updates must extend the UpdateMessage class. We also show the declaration of the ChatUpdateDelegate class.

Upon reception, the client calls the processUpdate callback that ChatUpdate overrides from the UpdateMessage class. We implement processUpdate in a category of ChatUpdate so that, if we have to edit the structure of chat update, we can replace the generated source files without having to worry about losing the implementation of processUpdate. In this example, the client accesses the application scope to access a delegate for chat updates, and then informs that delegate that it has been received. The delegate is simply a class that implements the ChatUpdateListener protocol that has registered itself with the application scope to recieve updates when ChatUpdates are recieved. You'll notice in the Client section that our client registers itself in the application scope as the CHAT_UPDATE_DELEGATE.

extern NSString * const CHAT_UPDATE_DELEGATE;


@protocol ChatUpdateDelegate

  - (void) recievedChatUpdate:(ChatUpdate*)update;

@end

#import "ChatUpdate.h"


@implementation ChatUpdate


@synthesize message;

@synthesize host;

@synthesize port;


+ (void) initialize {

[ChatUpdate class];

}


- (void) dealloc {

[message release];

[host release];

}


- (void) setPortWithReference: (int *) p_port {

port = *p_port;

}


@end

#import "ChatUpdateImpl.h"

#import "ChatUpdateDelegate.h"


@implementation ChatUpdate (Implementation)


-(void) processUpdate:(Scope *) scope

{

/*

* Get reference to the CHAT_UPDATE_DELEGATE

* out of the application scope.

*/

NSValue* updateDelegatePtr = (NSValue*)

[scope objectForKey:CHAT_UPDATE_DELEGATE];


id<ChatUpdateDelegate> updateDelegate = (id<ChatUpdateDelegate>)

 [updateDelegatePtr pointerValue];

/*

* updateDelegate may be nil but we can send a selector to nil

*/

[updateDelegate recievedChatUpdate:self];

}


@end

Client Instantiation

We now give the implementation for the client (shown to the right). Note that in the applicationDidFinishLaunching method the application registers the ChatRoomViewController (which implements the ChatUpdateDelegate protocol) as the CHAT_UPDATE_DELEGATE with the application scope. Also note that ChatAppDelegate implements the XMLClientDelegate protocol. This allows it to receive notifications of the change in state of the client's state. The client is implemented as a simple iPhone application that allows the user to read their previous messages along with new messages being posted to the service.

When the user presses the return button the textFieldShouldReturn method in ChatRoomViewController.m is invoked. Here we instantiate a new ChatRequest message and send it to the server to post the message. When a ChatRequest is recieved the server sends a ChatUpdate messages to the other clients. The client then simply updates the text area to reflect the new message.

The applicationDidFinishLaunching method in ChatAppDelegate.m sets up an XMLClient (the equivalent of the java NIOClient) with the ChatTranslations translation scope. It also connects the client, and sets up the ChatRoomViewController. We give the implementation of ChatTranslations, ChatAppDelegate, and ChatRoomViewController below.

@implementation ChatTranslations


static TranslationScope* theScope;


/*

 * Class level accessor for ChatTranslations

 */

+(TranslationScope*) get

{

  if(theScope == nil)

  { 

    /*

     * Initiate translation scope with xml file resource.

     */

    NSString *path = [[[NSBundle mainBundle] resourcePath] 

                       stringByAppendingPathComponent: @"ChatTranslations.xml"];


    theScope = [[[TranslationScope alloc] initWithXMLFilePath: path] retain];

  }

  

  return theScope;

}


@end

@implementation ChatAppDelegate


@synthesize window;

@synthesize chatRoomViewController;

@synthesize client;


- (void)applicationDidFinishLaunching:(UIApplication *)application 

{         

  /*

   * Get an instance of the ChatTranslations scope.

   */

  TranslationScope* scope = [ChatTranslations get];

    

  /*

   * Initialize the client with the ChatTranslations scope.

   */

  self.client = [[XMLClient alloc] initWithHostAddress:@"shady.cse.tamu.edu"

                                   andPort:2108 

                                   andTranslationScope:scope];


  /*

   * Designate self as the client's delegate.

   */

  self.client.delegate = self;

  

  /*

   * Set the ChatRoomViewController's client as the client.

   */

  chatRoomViewController.client = self.client;

  

  /*

   * Set up the chatRoomViewController as 

   * the CHAT_UPDATE_DELEGATE in the application scope.

   */

  [self.client.scope setObject:

                     [NSValue valueWithPointer:(chatRoomViewController)]

                     forKey:CHAT_UPDATE_DELEGATE];

  

  /*

   * Connect the client to the server.

   */

  [self.client connect];

  

  [window addSubview:chatRoomViewController.view];

  [window makeKeyAndVisible];

  

}



- (void)dealloc {

  [chatRoomViewController release];

  [window release];

  [super dealloc];

}


/*

 * Show chat room

 */

- (void)showChatRoom

{

  [chatRoomViewController activate];  

  [window bringSubviewToFront:chatRoomViewController.view];

}




/*

 * XMLClientDelegate methods:

 */

- (void) connectionTerminated:(XMLClient*)client

{

  NSLog(@"The connection terminated!\n");

  

}


- (void) connectionAttemptFailed:(XMLClient*) connection

{

  NSLog(@"The connection failed to connect!\n");

}


- (void) connectionSuccessful:(XMLClient*) client 

         withSessionId:(NSString*) sessionId;

{

  /*

   * Show the chat window after the client has connected.

   */ 

  [window bringSubviewToFront:chatRoomViewController.view];

  [self showChatRoom];

  

  NSLog(@"Connection successful with session id:%@\n", sessionId);

}


/*

 * Close the connection when the user hits the home button.

 */

- (void) applicationWillTerminate:(UIApplication*) application

{

  [client disconnect];

}

@end


@implementation ChatRoomViewController


@synthesize client;


/*

 * Add a chat message

 */

- (void)displayChatMessage:(NSString*)message 

        fromUser:(NSString*)userName 

{

  [chat appendTextAfterLinebreak:

        [NSString stringWithFormat:@"%@: %@", userName, message]];

  [chat scrollToBottom];

}


/*

 * ChatUpdateDelegate method.

 */

- (void) recievedChatUpdate:(ChatUpdate*)update;

{

  /*

   * Build username (ip:port) and post to chat area.

   */

  NSString* user = [NSString stringWithFormat:@"%@:%d", 

                             update.host, update.port];

  [self displayChatMessage:update.message fromUser:user];

}


#pragma mark -

#pragma mark UITextFieldDelegate Method Implementations


/*

 * This is called whenever "Return" is touched on iPhone's keyboard

 */

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {

if (theTextField == input) {

NSString* inputText = input.text;

       

    /*

     * Initialize ChatRequest and set message to content's of the text field.

     */

    ChatRequest* request = [[ChatRequest alloc] init];

    [request setMessage:inputText];

    

    /*

     * Setup the client to send the message a little later in

     * the run loop.

     */

    [client performSelector:@selector(sendMessage:) withObject: request];

    

    [request release];


[input setText:@""];

    [self displayChatMessage:inputText fromUser:@"me"];

}

return YES;

}


- (void)activate {

  [input becomeFirstResponder];

}


- (void)dealloc {

  [super dealloc];

}


@end

designed for mozilla 1+ and ie 6+
an interface ecology lab production