Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Mar 31, 2009, 05:51 PM   #1
Raska
macrumors 6502
 
Join Date: Aug 2007
Location: NJ
NSConnection Issue

I am creating two applications: a command-line Foundation application, and a Cocoa application. The command-line will be the server, and the Cocoa is the client.

The Server code is as follows:
Code:
theConnection = [NSConnection serviceConnectionWithName: @"atcserver" rootObject: planes];
			
if(theConnection == nil) NSLog(@"Error creating Server!");
			
			
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(clientHasConnected:) name: NSConnectionDidInitializeNotification object: theConnection];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(connectionHasDied:) name: NSConnectionDidDieNotification object: theConnection];
			
[theConnection setDelegate: self];
			
//Make sure the connections runs on its own thread
[theConnection runInNewThread];
//Remove the connection from the main run loop so all requests run on the specified thread
[theConnection removeRunLoop: [NSRunLoop currentRunLoop]];
The Client code is as follows:
Code:
theConnection = [NSConnection connectionWithRegisteredName: @"atcserver" host: nil];
remoteObject = (NSMutableArray *)[[theConnection rootProxy] retain];
			
if (theConnection == nil) {
	NSLog(@"Could not connect to server!");
	exit(1);
}
else {
	//Add self to the notification center to let it know if the connection has initalized or died
	[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(connectionHasDied:) name: NSConnectionDidDieNotification object: theConnection];
	//Make sure the connections runs on its own thread
	[theConnection runInNewThread];
	//Remove the connection from the main run loop so all requests run on the specified thread
	[theConnection removeRunLoop: [NSRunLoop currentRunLoop]];
}
Where both 'theConnection' objects are NSConnections, and 'remoteObject' in the Client is of type id. It appears as though the client connects to the server, but when I attempt to call a method on remoteObject, I get the following error message:
Quote:
2009-03-31 18:50:22.087 ATCClient[2243:10b] *** -[NSCFArray remoteMethod]: unrecognized selector sent to instance 0x12ee70
2009-03-31 18:50:22.089 ATCClient[2243:10b] Error! *** -[NSCFArray remoteMethod]: unrecognized selector sent to instance 0x12ee70
I have been racking my brain for what seems like forever but cannot figure out the problem. Any help would be greatly appreciated. Thanks in advance!
__________________
Crystalwell Retina Macbook Pro, 2.3/16/512
32GB Black Retina iPad Wifi
32GB White iPhone 5 (Verizon)
Raska is offline   0 Reply With Quote
Old Mar 31, 2009, 08:55 PM   #2
kainjow
Moderator emeritus
 
kainjow's Avatar
 
Join Date: Jun 2000
What is "planes"?
kainjow is offline   0 Reply With Quote
Old Mar 31, 2009, 09:55 PM   #3
Raska
Thread Starter
macrumors 6502
 
Join Date: Aug 2007
Location: NJ
"planes" is an NSMutableArray which will hold custom Plane objects.
__________________
Crystalwell Retina Macbook Pro, 2.3/16/512
32GB Black Retina iPad Wifi
32GB White iPhone 5 (Verizon)
Raska is offline   0 Reply With Quote
Old Mar 31, 2009, 11:17 PM   #4
kainjow
Moderator emeritus
 
kainjow's Avatar
 
Join Date: Jun 2000
I suspect something is going on in some of your other code. I first thought it was an issue with using an array as the root object, but that's not the problem. Can you post more code?

I would suggest not using NSMutableArray as the root object. Instead, use a custom object that conforms to your own protocol. This way you can set the protocol on the proxy object in the client via setProtocolForProxy: which reduces the amount of messages sent back and forth from the client and server.

BTW I created a test project and it works just fine using this bare minimum code:

Code:
// Server
- (void)applicationDidFinishLaunching:(NSNotification *)notif
{
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addObject:@"Hello"];
    NSConnection *conn = [NSConnection serviceConnectionWithName:@"testconn" rootObject:array];
    [conn runInNewThread];
}

// Client
- (void)applicationDidFinishLaunching:(NSNotification *)notif
{
    NSConnection *conn = [NSConnection connectionWithRegisteredName:@"testconn" host:nil];
    NSMutableArray *arrayProxy = (NSMutableArray *)[conn rootProxy];
    [arrayProxy addObject:@"World"];
    NSLog(@"arrayProxy: %@", arrayProxy);
}
kainjow is offline   0 Reply With Quote
Old Mar 31, 2009, 11:27 PM   #5
Raska
Thread Starter
macrumors 6502
 
Join Date: Aug 2007
Location: NJ
All right I'll take care of the protocol. As for the current situation, here is my entire .m file for the server:
Code:
#import "ATCModel.h"
#import "Plane.h"

@implementation ATCModel

-(id)init {
	self = [super init];
	
    if (self) {
		planes = [[NSMutableArray alloc] init];
		[self startServer];
    }
	
	return self;
}

-(void)startServer {	
	//Engage Mutual Exclusion
	@synchronized(self) {
		@try {
			theConnection = [NSConnection serviceConnectionWithName: @"atcserver" rootObject: planes];
			
			if(theConnection == nil) NSLog(@"Error creating Server!");
			
			
			[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(clientHasConnected:) name: NSConnectionDidInitializeNotification object: theConnection];
			[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(connectionHasDied:) name: NSConnectionDidDieNotification object: theConnection];
			
			[theConnection setDelegate: self];
			
			//Make sure the connections runs on its own thread
			[theConnection runInNewThread];
			//Remove the connection from the main run loop so all requests run on the specified thread
			[theConnection removeRunLoop: [NSRunLoop currentRunLoop]];
			
			NSLog(@"Waiting for connections...");
		}
		@catch (NSException *anError) {
			//If cannot connect to server, report error and exit application
			[self dealloc];
			NSLog(@"Error: Could not create server! %@", anError);
			exit(1);
		}
	}
}

-(void)clientHasConnected {
	NSLog(@"A Client has connected to the server!");
}

-(void)connectionHasDied {
	NSLog(@"Connection has died. Reconnecting...");
	//Engage Mutual Exclusion
	@synchronized(self) {
		//Clear out the connection and remove self from notifications
		[[theConnection sendPort] invalidate];
		[[theConnection receivePort] invalidate];
		[theConnection release];
		theConnection = nil;
		[[NSNotificationCenter defaultCenter] removeObserver: self name: NSConnectionDidDieNotification object: theConnection];
		[[NSNotificationCenter defaultCenter] removeObserver: self name: NSConnectionDidInitializeNotification object: theConnection];
		
		//Restart the server
		[self startServer];
	}
}

-(void)dealloc {
	[theConnection release];
	[planes release];
	[super dealloc];
}

-(void)remoteMethod {
	NSLog(@"Remote Method called!");
}

@end
and for the client:
Code:
#import "ATCController.h"


@implementation ATCController

-(void)awakeFromNib {
	NSLog(@"Starting Client...");
	[self connectToServer];
}

-(void)connectToServer {
	//Engage Mutual Exclusion
	@synchronized(self) {
		@try {								
			theConnection = [NSConnection connectionWithRegisteredName: @"atcserver" host: nil];
			remoteObject = (NSMutableArray *)[[theConnection rootProxy] retain];
			
			if (theConnection == nil) {
				NSLog(@"Could not connect to server!");
				exit(1);
			}
			else {
				//Add self to the notification center to let it know if the connection has initalized or died
				[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(connectionHasDied:) name: NSConnectionDidDieNotification object: theConnection];
				//Make sure the connections runs on its own thread
				[theConnection runInNewThread];
				//Remove the connection from the main run loop so all requests run on the specified thread
				[theConnection removeRunLoop: [NSRunLoop currentRunLoop]];
				
				[remoteObject remoteMethod];
			}
		}
		@catch (NSException *anError) {
			//If cannot connect to server, report error and exit application
			NSLog(@"Error! %@", anError);
			exit(1);
		}
	}
}

-(void)connectionEstablished {
	NSLog(@"Connection to server established!");
}

-(void)connectionHasDied {
	//Engage Mutual Exclusion
	@synchronized(self) {
		NSLog(@"Connection to Server has died. Reconnecting...");
		//Clear out and the connection and remove self from notifications
		[[theConnection sendPort] invalidate];
		[[theConnection receivePort] invalidate];
		[theConnection release];
		theConnection = nil;
		[[NSNotificationCenter defaultCenter] removeObserver: self name: NSConnectionDidDieNotification object: theConnection];
		
		//Reconnect to the server
		[self connectToServer];
	}
}

-(void)dealloc {
	[theConnection release];
	[remoteObject release];
	[super dealloc];
}

@end
__________________
Crystalwell Retina Macbook Pro, 2.3/16/512
32GB Black Retina iPad Wifi
32GB White iPhone 5 (Verizon)
Raska is offline   0 Reply With Quote
Old Mar 31, 2009, 11:34 PM   #6
kainjow
Moderator emeritus
 
kainjow's Avatar
 
Join Date: Jun 2000
Ah . I thought remoteMethod was a private method of NSDistantObject, which was confusing me.

You are calling remoteMethod on the proxy object, which is an NSMutableArray, so that's why that error is occurring. I'd suggest setting the root object in your server to "self" (instead of "planes") and then provide an accessor to access the planes array.

Edit: never call dealloc. Cocoa does that for you when your object is being deallocated.

Last edited by kainjow; Mar 31, 2009 at 11:39 PM.
kainjow is offline   0 Reply With Quote
Old Apr 1, 2009, 09:21 AM   #7
Raska
Thread Starter
macrumors 6502
 
Join Date: Aug 2007
Location: NJ
That did the trick! Thank you so much!

Regarding setting a protocol, if I have the root object set to self, would setting up a protocol on my custom object still be effective?
__________________
Crystalwell Retina Macbook Pro, 2.3/16/512
32GB Black Retina iPad Wifi
32GB White iPhone 5 (Verizon)
Raska is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
thread Thread Starter Forum Replies Last Post
OS X printing sharing issue WRXface OS X 1 Feb 25, 2011 06:44 PM
Another screen issue thread: I can't find one that has the same issues carreragt7 MacBook 5 Jan 2, 2011 11:14 AM
Canon 60D issue - horizontal banding on dark colours Schtumple Digital Photography 13 Dec 25, 2010 03:57 AM
MacBook Pro Unibody bootup issue, videos included MIDI_EVIL MacBook Pro 14 Dec 9, 2010 12:58 PM
Heating issues? tljuly3 MacBook Air 4 Nov 16, 2010 06:16 PM


All times are GMT -5. The time now is 10:21 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC