Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > Cocoa Newbie: Messaging Between Objects

Cocoa Newbie: Messaging Between Objects
Thread Tools
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jan 31, 2003, 01:06 AM
 
I'm learning Cocoa and one of my experiments consists of trading messages between two subclasses of NSObject which we I call "Controller" and "Helper". How do I get the Helper object to correctly reference the Controller so that a method in Helper calls a method in the Controller.

Here's what I did. I created an outlet in the Helper class for pointing to the Controller object. I then connected that outlet to the Controller instance. I thought that would do the trick but I get the following runtime error:

2003-01-31 00:50:09.547 test[1646] *** -[Controller printMessage]: selector not recognized

I speculate that the problem is that my code correctly points to the Controller object but then the runtime cannot find the printMessage method. What am I missing?

Thanks!
     
Addicted to MacNN
Join Date: May 2001
Location: Cupertino, CA
Status: Offline
Reply With Quote
Jan 31, 2003, 01:21 AM
 
Unless printMessage is a class method, you will want to send the message to an instance of Controller... this instance should be the outlet you created. Calling [Controller printMessage] sends the class Controller the printMessage message.
     
Mac Elite
Join Date: May 2002
Status: Offline
Reply With Quote
Jan 31, 2003, 10:01 AM
 
He wasn't calling [Controller printMessage], that's just the way the console displays the error.
[vash:~] banana% killall killall
Terminated
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jan 31, 2003, 10:12 AM
 
Thanks for the response. What you're saying makes sense to me but my implementation effort it is not going well. My confusion is stemmed from the fact that I thought I had actual instances of both the Controller and Helper because I saw the their cube icons in the MainMenu.nib and you have to "instantiate" the classes in IB in order to get to this stage. Are they just proxies for instances?

Anyway, after following your advice (I "think" I did) I still get a "selector not recognized".

Here's what the Helper code looks like:

--------------------------------------

/* Helper */

#import <Cocoa/Cocoa.h>
#import "Controller.h"

@interface Helper : NSObject
{
IBOutlet NSTextView *textBox;
IBOutlet id toController;
//Controller *ControllerInstance;

}
- (IBAction)printNumbers:(id)sender;
@end


--------------------------------------

#import "Helper.h"

@implementation Helper

- (void) awakeFromNib{
toController = [[Controller alloc] init];
}


- (IBAction)printNumbers:(id)sender
{
[textBox insertText:@"Helper object sends these numbers: 0123456789\n"];
[toController printMessage2];

}

@end

--------------------------------------

Thanks!
:)
     
Addicted to MacNN
Join Date: Mar 2000
Location: London, UK
Status: Offline
Reply With Quote
Jan 31, 2003, 10:23 AM
 
You don't include the Controller code...
     
Professional Poster
Join Date: Apr 2001
Location: Long Beach, CA
Status: Offline
Reply With Quote
Jan 31, 2003, 10:59 AM
 
You are breaking the Interface Builder connections in your awakeFromNib function. Remove the assignment and it should work (assuming the connections in IB are correct).

Also, as Angus_D noted, we don't have the code to the controller object. Without that, it definitely won't work. In IB, you can create class and instantiate them without writing a single line of code. However, nothing will happen unless you write that code.

ACSA 10.4/10.3, ACTC 10.3, ACHDS 10.3
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jan 31, 2003, 11:34 AM
 
Thanks for all the posts. Below is the complete code. Some lines have been commented out as a consenquence of my trial-and-error approach. I really prefer to understand what I'm doing...

it's a bit confusing... I see why we need the cube icons in the MainMenu.nib. Are they true instances or are they really proxies for instances given that at that stage nothing has been compiled yet?

In any event, here's all the code:

----------------------------------
Controller.h
----------------------------------

#import <Cocoa/Cocoa.h>

@interface Controller : NSObject
{
IBOutlet NSTextView *textBox;
}
- (IBAction)eraseMessage:(id)sender;
- (IBAction)printMessage:(id)sender;
- (IBAction)printMessage2:(id)sender;
- (IBAction)printMessage3:(id)sender;

@end


----------------------------------
Controller.m
----------------------------------

#import "Controller.h"

@implementation Controller


- (IBAction)printMessage:(id)sender
{
[textBox insertText:@"Hello World! This is message 1\n"];
}

- (IBAction)printMessage2:(id)sender
{
[textBox insertText:@"Hello World! This is message 2\n"];
}

- (IBAction)printMessage3:(id)sender
{
[textBox insertText:@"Hello World! The helper object sent me\n"];
}

@end


----------------------------------
Helper.h
----------------------------------

#import <Cocoa/Cocoa.h>
#import "Controller.h"

@interface Helper : NSObject
{
IBOutlet NSTextView *textBox;
IBOutlet id toController;
//Controller *ControllerInstance;

}
- (IBAction)printNumbers:(id)sender;
@end


----------------------------------
Helper.m
----------------------------------

#import "Helper.h"

@implementation Helper

// - (void) awakeFromNib{
// toController = [[Controller alloc] init];
// }


- (IBAction)printNumbers:(id)sender
{
[textBox insertText:@"Helper object sends these numbers: 0123456789\n"];
[toController printMessage2];

}

@end
     
Professional Poster
Join Date: Apr 2001
Location: Long Beach, CA
Status: Offline
Reply With Quote
Jan 31, 2003, 11:43 AM
 
here's the code error:

in your function printNumbers, your call to printMessage2 is actually incorrect. This function has a single argument, as dictated by IB. It should be something along the lines of:

[toController printMessage2: self];

To answer your question about the instances in the IB files: they are actual instances. There are several functions that may be called before the connections are made. Off the top of my head, I don't remember them.

BTW: the "selector not recognized" error means that the function call does not exist as you attempted to call it.

ACSA 10.4/10.3, ACTC 10.3, ACHDS 10.3
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jan 31, 2003, 12:15 PM
 
Thanks, It worked correctly after including the self argument in the printMessage2 method.

Alas, now the mechanics are correct but some concepts are still foggy...

I have yet to understand, why do we need the self argument? I thought that by having a connection from the "toController" outlet within Helper to the Controller instance was sufficient to resolve any ambiguity. After all, there is only one instance of Controller available. Is the self argument needed to distinguish from user created instances as opposed to the one created by IB?


     
Professional Poster
Join Date: Apr 2001
Location: Long Beach, CA
Status: Offline
Reply With Quote
Jan 31, 2003, 12:49 PM
 
Originally posted by DaGuy:
Thanks, It worked correctly after including the self argument in the printMessage2 method.

Alas, now the mechanics are correct but some concepts are still foggy...

I have yet to understand, why do we need the self argument? I thought that by having a connection from the "toController" outlet within Helper to the Controller instance was sufficient to resolve any ambiguity. After all, there is only one instance of Controller available. Is the self argument needed to distinguish from user created instances as opposed to the one created by IB?


The self argument is just to fulfil the requirements for an argument. You could pass nil or 42. It wouldn't make a difference.

Like the following function:

Code:
void donothing(int value) { return; }
despite the fact that nothing is done with "value," you still have to pass an integer when you call the function. The (id)sender argument is there so that you can figure out which button was pressed if you have multiple buttons calling the same function... or any other use you can come up with. Whether you use it or not, it has to be there because it's part of the function definition.

ACSA 10.4/10.3, ACTC 10.3, ACHDS 10.3
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jan 31, 2003, 01:04 PM
 
That makes sense. Thanks very much to you and everyone else who assisted. I will keep chugging along and see what else pops up -there's plenty out there.

     
   
Thread Tools
Forum Links
Forum 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
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 02:08 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2