• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Forwarding key events to a non first responder?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Forwarding key events to a non first responder?


  • Subject: Re: Forwarding key events to a non first responder?
  • From: Phillip Morelock <email@hidden>
  • Date: Wed, 12 Jun 2002 15:45:00 -0700

Re: the first responder delegation problem

Some (unchecked) sample code (concept of it directly lifted from the
article):

#include <objc/objc-class.h>
#include<string.h>

...

- (id) aNormalMethodWeAreOverriding: (id) someArg
{
static IMP superselector = nil;

id retval;

if ( superselector == nil)
{
superselector = __myLookup( self->isa,
"aNormalMethodWeAreOverriding", "id" );
}

__doMyFunkyDanWoodStuff( someArg );

retval = __myRealityDispatcher( self->isa, superselector, someArg );
return retval;

}

and somewhere previously defined:

void __doMyFunkyDanWoodStuff( id someArg )
{
static NSTableView *tableView = nil;

if (tableView == nil)
{
tableView = [MyGlobalClass tableView];
}

if (the arg meets my criteria)
{
[tableView send: the: message: i: wanted: to: send:];
}
}

IMP __myLookup(struct objc_class *l_isa, const char *target, const char
*types )
{
const char *my_meth_name;
const char *my_meth_types;
IMP retimp = nil;

struct objc_method *currMethod;
struct objc_method_list* mlist = l_isa->methodLists;

int j = 0;
int seen = 0;
int ct = mlist->method_count;

for ( ; j < ct && seen < 1; ++j )
{
currMethod = (mlist->method_list + j);

my_meth_name = (const char *)currMethod->method_name;
my_meth_types = currMethod->method_types;

if ( 0 == strcmp(my_meth_name, target)
&& 0 == strcmp(my_meth_types, types)
)
{
++seen;
retimp = currMethod->method_imp;
}
}

return retimp;
}

Now the real challenge would be to implement:
__myRealityDispatcher( self->isa, superselector );

That one is over my head at the moment. Of course, what I just wrote might
be bad news, too, YMMV. This is all pretty nasty. I really wish someone
would come on and say "no, it's much easier to work around this."

cheers
fillup

P.S. From the documentation for NSObject:

IMP is defined as a pointer to a function that returns an id and takes a
variable number of arguments (in addition to the two "hidden" arguments-self
and _cmd-that are passed to every method implementation):

typedef id (*IMP)(id, SEL, ...);


On 6/12/02 2:12 PM, "Phillip Morelock" <email@hidden>
wrote:

>> Any suggestions to accomplish this somewhat gracefully?
>
> Not gracefully, but...
>
> This problem got me thinking...a little hacking is my best idea for a
> solution at this point.
>
> http://www.macdevcenter.com/pub/a/mac/2002/05/31/runtime_parttwo.html
>
> From this article about the Objective C runtime, where he talks about the
> structure of objects, he talks about the structures that you can point into
> to find overridden methods.
>
> "During method lookup, the runtime traverses the arrays of methods in the
> order they are stored. That order is the reverse of the order in which each
> group of methods is loaded. As the class must be loaded before categories
> are added to the class, the methods declared in a class itself are always
> loaded first, so end up last in the list. Since the runtime does method
> lookups from first-to-last, a category method will always override a method
> declared in the class itself. "
>
> Relevant code / header snippets:
>
> struct objc_class
> {
> struct objc_class *isa;
> struct objc_class *super_class;
> const char *name;
> long version;
> long info;
> long instance_size;
> struct objc_ivar_list *ivars;
> ------> struct objc_method_list **methodLists; <--------
> struct objc_cache *cache;
> struct objc_protocol_list *protocols;
> };
>
> and:
> void showMethodGroups(Class klass, char mType) {
> void *iterator = 0; // Method list (category) iterator
> struct objc_method_list* mlist;
> Method currMethod;
> int j;
> while ( mlist = class_nextMethodList( klass, &iterator ) ) {
> printf (" Methods:\n");
> for ( j = 0; j < mlist->method_count; ++j ) {
> currMethod = (mlist->method_list + j);
> printf (" method: '%c%s' encodedReturnTypeAndArguments: '%s'\n",
> mType,
> (const char *)currMethod->method_name,
> currMethod->method_types);
> }
> }
> }
>
>
> So, yesterday I suggested hacking NSResponder, and this is just me looking
> into it because this problem is nagging my brain. You see how the above
> makes it possible. To do it, you could (caveat emptor) just put a category
> on NSResponder and override the dispatcher methods to make sure a message
> gets sent to your tableview. Then you could walk the instance method list
> and find the "real" implementation to pass the call to (obviously caching it
> after the first lookup). This reminds me of that isa-swizzling light
> flamewar of last week, so obviously buyer beware.
>
> Idea Number 2: Here's my new idea, which I think is feasible if you don't
> have too much to implement. Subclass the views that you're using as first
> responders but want to pass their events to the table. Override the
> appropriate NSResponder methods and call to [super]. There may be a
> non-obvious-to-fillup reason why that wouldn't work. But at least at first
> glance it appears to work without too much swizzling.
>
>
> HTH
> fillup
>
>
> On 6/11/02 9:58 PM, "Dan Wood" <email@hidden> wrote:
>
>> The subject line probably doesn't explain my question well
>> enough. Essentially what I'd like to do is have a big
>> NSTableView on a window that may or may not actually be first
>> responder -- perhaps there are some buttons or text fields on
>> the window. I'd like to be able to have keys that are
>> interesting to the NSTableView -- e.g. up/down arrows, page up &
>> page down -- essentially "forwarded" to the NSTableView, even if
>> something else is actually first responder. That would make it
>> much more intuitive for somebody to make use of the window, not
>> having to "tab into" the table (especially useless since there
>> is no highlighting shown when the table is first responder.
>>
>> Any suggestions to accomplish this somewhat gracefully?
>>
>>
>> --
>> Dan Wood
>> Karelia Software, LLC
>> email@hidden
>> http://www.karelia.com/
>> Watson for Mac OS X: http://www.karelia.com/watson/
>> _______________________________________________
>> cocoa-dev mailing list | email@hidden
>> Help/Unsubscribe/Archives:
>> http://www.lists.apple.com/mailman/listinfo/cocoa-dev
>> Do not post admin requests to the list. They will be ignored.
> _______________________________________________
> cocoa-dev mailing list | email@hidden
> Help/Unsubscribe/Archives:
> http://www.lists.apple.com/mailman/listinfo/cocoa-dev
> Do not post admin requests to the list. They will be ignored.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

References: 
 >Re: Forwarding key events to a non first responder? (From: Phillip Morelock <email@hidden>)

  • Prev by Date: Re: Thoughts on CodeWarrior 8 for Cocoa programming?
  • Next by Date: Doing the two-step?
  • Previous by thread: Re: Forwarding key events to a non first responder?
  • Next by thread: Re: Forwarding key events to a non first responder?
  • Index(es):
    • Date
    • Thread