Remi’s Chat App
Posted: July 18th, 2010 | Author: Remi | Filed under: Cocoa, Programming, iPhone | No Comments »As promised, here is some example code for the iPhone using ThoMoNetworking. I call it Remi’s Chat App. The mobile companion to Remi’s Chat Program.

Sorry it took me so long to put it up. Some things to note: It interfaces with Remi’s Chat Program in everything except that iOS doesn’t support the rich text. You may notice if you download the project that I created a file called NSPatches, this was to allow for the iOS to properly unarchive some classes that it doesn’t have, most notably NSFont. Other then that, from what I can tell ThoMoNetworking works flawlessly on iOS. The only thing I couldn’t test was from iOS to iOS, since I lacked two iOS devices, but from iOS to OS X worked great, so I would assume it would work fine. So here is the bulk of the code for you to peruse, and you can download the project underneath, enjoy!
P.S. Let me know if anybody runs into any issues with the code, I may be able to resolve them easily, since some crashes might just be due to iOS not having certain clases that OS X has, which a simple appending to the NSPatches file should fix.
// // Remi_s_Chat_AppViewController.m // Remi's Chat App // // Created by Remi Bernotavicius on 7/18/10. // Copyright __MyCompanyName__ 2010. All rights reserved. // #import "Remi_s_Chat_AppViewController.h" @implementation Remi_s_Chat_AppViewController /* // The designated initializer. Override to perform setup that is required before the view is loaded. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { // Custom initialization } return self; } */ /* // Implement loadView to create a view hierarchy programmatically, without using a nib. - (void)loadView { } */ // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; myServer = [[ThoMoServerStub alloc] initWithProtocolIdentifier:@"remischat"]; [myServer setDelegate:self]; [myServer start]; myClient = [[ThoMoClientStub alloc] initWithProtocolIdentifier:@"remischat"]; [myClient setDelegate:self]; [myClient start]; [[UIApplication sharedApplication] setDelegate:self]; } - (void)applicationWillTerminate:(UIApplication *)application { NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" disconnected"]] autorelease]; [temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]]; [myServer sendToAllClients:temp]; } - (void)server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString; { NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" connected"]] autorelease]; [temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]]; [myServer send:temp toClient:aClientIdString]; } /* // Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } */ - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } - (void)viewDidUnload { // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (void)textFieldDidBeginEditing:(UITextField *)textField { CGRect newFrame = self.view.frame; if ([[UIApplication sharedApplication] statusBarOrientation]== UIInterfaceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) newFrame.size.height -= 216; else newFrame.size.height -= 162; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:0.3]; [self.view setFrame:newFrame]; [UIView commitAnimations]; } -(IBAction)sendMessage:(id)sender { NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@": "]] autorelease]; [temp appendAttributedString:[[[NSMutableAttributedString alloc] initWithString:toSend.text] autorelease]]; [temp appendAttributedString:[[[NSMutableAttributedString alloc] initWithString:@"\n"] autorelease]]; [myServer sendToAllClients:temp]; toSend.text = @""; } - (void)textFieldDidEndEditing:(UITextField *)textField { CGRect newFrame = self.view.frame; if ([[UIApplication sharedApplication] statusBarOrientation]== UIInterfaceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) newFrame.size.height += 216; else newFrame.size.height += 162; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:0.3]; [self.view setFrame:newFrame]; [UIView commitAnimations]; } -(void)server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString {} -(void)client:(ThoMoClientStub *)theClient didReceiveData:(id)theData fromServer:(NSString *)aServerIdString; { NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithAttributedString:theData] autorelease]; history.text = [history.text stringByAppendingString:[temp string]]; [history scrollRangeToVisible:NSMakeRange([history.text length]-2, 1)]; } - (void)dealloc { [super dealloc]; } @end |
After enabling it you will be prompted for your Gmail username and password. Then you should see a sync icon in your status bar. This lets you manually force a sync with google by clicking “sync now.” When it syncs you will probably have to resolve some ‘sync issues’ (basically deciding which contact is correct, the Gmail or Address Book version.)
Remember that this makes your contacts instantly updated from your computer to google, but no the other way around. The frequency that the contacts come into your computer from google is determined by the “run it every” setting. I do not know why apple did not have the file set to watch the address book database to begin with, so I’m not sure if there are any adverse effects, but there has been none that I have experienced so far. Once you are finished editing the job, hit save, then log out and back in or restart for it to take effect. To try it out just edit one of your contacts in Address Book.app and see the update automatically appear on Gmail, and if you iPhone is synced to Gmail, then right to your iPhone.