Re: IBoutlets out of scope in c functions?
Re: IBoutlets out of scope in c functions?
- Subject: Re: IBoutlets out of scope in c functions?
- From: Derrick Bass <email@hidden>
- Date: Fri, 10 Mar 2006 11:57:08 -0600
On Mar 10, 2006, at 7:03 AM, Mike Lehmann wrote:
@interface Controller : NSObject
{
IBOutlet id bellMessage;
IBOutlet id conversation; // This is the IBOutlet in question
IBOutlet id watsonMessage;
IBOutlet id watsonStatus;
}
Okay, unrelated comment. You should probably statically type these,
instead of calling them all "id". I.e. if conversation is an
NSTextView, then declare it as
IBOutlet NSTextView* conversation;
That will allow the compiler to warn you if it looks like you are
sending messages to an object that can't respond to them, instead of
waiting for runtime to get an error message.
// If I build with this line uncommented, I receive the
following error:
// 'conversation was not declared in this scope
unsigned int loc = [[conversation textStorage] length];
Right, because conversation is an undeclared variable. (It has
nothing to do with IBOutlets, by the way. IBOutlet, as far as the
compiler is concerned, is #defined to nothing. It's just there to
tell IB when reading the header that it should add that to the
"outlets" list and to tell readers of the code that this pointer will
be filled in by the NIB reading mechanism rather than in init or some
other place in the code.)
Jonathon Mah already mentioned the answer, so I'll just elaborate to
the same novel length as your original question. This sort of things
would come up in pure C and C++ too when you use callbacks. Usually
the callback needs not only to know what function to call, but also
some data that needs to be passed to the function. Since you are
familiar with C++, I'll try to explain in that language.
[[conversation textStorage] length];
is analogous to (note: not identical to; C++ classes and Objective-C
classes are not the same thing and don't respond to the same syntax)
the C++ statement
conversation->textStorage()->length();
Obviously that wouldn't work if you hadn't passed an object named
conversation to your function somehow. In addition to a function
pointer, you'll also need to pass a pointer to some storage into your
Chatter class. In this case, you can simply pass in the pointer to
the NSTextView object; however, you might want to pass in the
controller object itself (that would allow for better separation of
the details of the user interface; you're C code wouldn't need to
know exactly how text was displayed, it would just send a string to a
function in Controller).
- (IBAction)sendWatsonChatter:(id)sender
{
[snip]
PF myFuncPtr = printChatter;
Chatter myChatter( myFuncPtr );
Assuming you pass in the whole controller, as I recommended,
Chatter myChatter( myFuncPtr, self )
Then printChatter would look like:
void printChatter( const string& inString, void *controller_vp ) {
// same code as before to convert inString to an NSString*
// ...
//
Controller *controller = reinterpret_cast<Controller*>(controller_vp);
[controller doSomethingWithString:chatterString];
}
If your C++ framework API is unchangeable and can only handle
pointers to functions like your original printChatter then
1. Your framework API is broken and needs to be changed.
2. If it can't be changed, you will have to store "conversation" (or
some other pointer that refers to your controller) in a global
variable. You will then have problems if you ever have more than one
conversation going at once and the C++ API needs to tell the GUI
which window to write to. This will be true no matter what language
you write the GUI in. You will then go back and change the C++ API,
but it will be much more painful because so much more code has been
written. ;-)
Derrick
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden