This comment has been minimized.

I'd be interested in hearing about that too. I tend to make these gigantic structs not because I care about caching, but rather because it's rather more elegant to check a flag than to litter my code with super-ugly -respondsToSelector: messages. And because I've learnt to be cautious with proxies.

I'd be interested in hearing about that too. I tend to make these gigantic structs not because I care about caching, but rather because it's rather more elegant to check a flag than to litter my code with super-ugly -respondsToSelector: messages. And because I've learnt to be cautious with proxies.

This comment has been minimized.

I'm sure there is, but it might be slightly different under ARC. You can't use -forwardingTargetForSelector:, because if you return nil from there, it will just try to use -forwardInvocation:. Basically:

Implement -methodSignatureForSelector: or whatever, using your target as a base.

Implement -forwardInvocation:. If your target responds to the selector, set the return value of the invocation to your target's address. If the target doesn't respond, set the return value to nil. You'll probably need to fiddle around with ownership qualifiers here (like __autoreleasing). Someone who has done this more recently than I have can probably help if you have trouble.

But remember! This is a whole new layer you have to debug. So, it's pretty cool to have, but make sure you're committed to making it perfect.

I'm sure there is, but it might be slightly different under ARC. You can't use -forwardingTargetForSelector:, because if you return nil from there, it will just try to use -forwardInvocation:. Basically:

Implement -methodSignatureForSelector: or whatever, using your target as a base.

Implement -forwardInvocation:. If your target responds to the selector, set the return value of the invocation to your target's address. If the target doesn't respond, set the return value to nil. You'll probably need to fiddle around with ownership qualifiers here (like __autoreleasing). Someone who has done this more recently than I have can probably help if you have trouble.

But remember! This is a whole new layer you have to debug. So, it's pretty cool to have, but make sure you're committed to making it perfect.

This comment has been minimized.

uhh... I really don't wanna mess around with NSInvocation, that would be orders of magnitude slower.
Isn't there a new way, what if we just do the respondsToSelector check in forwardingTargetForSelector and decide if we return the delegate target, and don't do anything in -forwardInvocation:? But still, I'm not sure if I wanna go there. Maybe a macro/inline function is the cleaner way.

uhh... I really don't wanna mess around with NSInvocation, that would be orders of magnitude slower.
Isn't there a new way, what if we just do the respondsToSelector check in forwardingTargetForSelector and decide if we return the delegate target, and don't do anything in -forwardInvocation:? But still, I'm not sure if I wanna go there. Maybe a macro/inline function is the cleaner way.

This comment has been minimized.

I prefer to check the respondsToSelector in place. Generally rather dislike such caches. I usually don't have that much delegate methods though...

However, you could build a proxy class that assembles method implementations automatically using runtime calls. That'd be extremely elegant, albeit a bit of work and probably shooting with canons on pigeons. You could open-source it afterwards though ;)

I prefer to check the respondsToSelector in place. Generally rather dislike such caches. I usually don't have that much delegate methods though...

However, you could build a proxy class that assembles method implementations automatically using runtime calls. That'd be extremely elegant, albeit a bit of work and probably shooting with canons on pigeons. You could open-source it afterwards though ;)

This comment has been minimized.

I like your approach, @hatfinch, but should the zeroing of the _delegates table not should happen first, and unconditionally, as the if statements only set the fields for methods that are present in the new delegate. If there was a previous setting for a field and the new delegate doesn't implement that method, the old value would still be present (causing the old delegate to be called for some methods).

Also, I believe that object refs in a struct are no longer allowed under ARC, but (__weak) ivars could work just as well.

I like your approach, @hatfinch, but should the zeroing of the _delegates table not should happen first, and unconditionally, as the if statements only set the fields for methods that are present in the new delegate. If there was a previous setting for a field and the new delegate doesn't implement that method, the old value would still be present (causing the old delegate to be called for some methods).

Also, I believe that object refs in a struct are no longer allowed under ARC, but (__weak) ivars could work just as well.