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

Similar Threads
thread Thread Starter Forum Replies Last Post
iOS 7 Orientation Issue - Hardware or Software Issue? GandalfBR iOS 7 6 Nov 16, 2013 04:56 PM
Hardware issue? Software issue? SSD beginning to die? oneMadRssn MacBook Air 11 Jun 5, 2013 12:00 PM
Font rendering issue with rMBP (Macbook issue or website issue?) Vinterbird MacBook Pro 8 Feb 27, 2013 10:42 AM
So has the Wi-Fi issue been determined to be a hardware issue or software issue? 1080p iPhone 0 Sep 25, 2012 12:11 AM
Macbook Pro Backlight Issue will swapping Display solve issue? Kayla90 MacBook Pro 4 Aug 24, 2012 01:38 PM

Forum Jump

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

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

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