NSConnection and multiple
threads (Distant Objects)
2006-12-02
Recently I had to deal with an error that was
strange:
The situation was like this: There are many threads
in a server application, for each client one, and
there are separate threads for special jobs that kind
of run in the background. We use distant objects and
hence proxies. Usually communication from the server
to the client is done from the thread that was
created for this client of the proxy we get when the
client registers. We use a NSConnection for this
purpose and acquire the proxy that the client is
offering.
To let our background processes use this proxy I had
enableMultipleThreads called in the
NSConnection object like the documentation states.
But I always got an NSObjectInaccessibleException.
Turns out you have to get the NSConnection from the
proxy and call enableMultipleThreads there:
...
NSDistantObject *myProxy =
[[myClientConnection rootProxy] retain];
NSConnection *connection = [myProxy
connectionForProxy];
[connection enableMultipleThreads];
...
Attention: You will get
back a pointer
2006-12-02
Sometimes you forget how old Objective-C really is.
Nowadays it is generally considered a bad idea to
give a client a pointer (or Object Reference in Java)
to an object that belongs solemnly to the client.
Usually you would expect a copy - that way the client
ensures encapsulation.
But what I often stumbled on is that classes from the
framework give back pointers instead. So be careful.
Those pointers may only be valid a very short time.
As an example:
You have a popup button and you'd like to change the
content. But you also want to keep the selected item,
in case it is still among the new content. You do
something like this:
...
NSString *selectedTitle = [[myPopupButton
selectedItem] title]; // should make a copy here!
[myPopupButton removeAllItems];
[myPopupButton addItemsWithTitles:
myArrayOfNewTitles];
[myPopupButton selectItemWithTitle:
selectedTitle]; //will crash here because
selectedTitle is no longer valid after the
removeAllItems call!
...
The same goes for the FieldEditor. You usually need
it when you want to check what the user entered in a
textfield but without ending text editing. So you
call the FieldEditor (only one instance per window)
like this:
-(void) controlTextDidChange: (NSNotification*)
aNotification
{
NSTextView *fieldEditor = [[aNotification
userInfo] objectForKey: @"NSFieldEditor"];
NSString *entry = [fieldEditor string];
// if you need this afterwards be sure to make a
copy!
...
}
So don't be surprised if you get back a pointer that
might change or gets invalid. Act safe and make a
copy of what you need to be around!
First Tuorial: Pifalls in
C
2006-06-05
As a first tutorial you will find a short description
of possible pitfalls and trips in C in regard to
Objective-C based on an article by Andrew König. Take
a look at the
tutorial.