Re: respondsToSelector - #import OR compiler warnings?
Re: respondsToSelector - #import OR compiler warnings?
- Subject: Re: respondsToSelector - #import OR compiler warnings?
- From: Bill Bumgarner <email@hidden>
- Date: Tue, 30 Dec 2008 11:39:46 -0800
Steve followed up to my response off-list.
My original post was... terse. I have had my coffee now. Let me
clarify a bit more...
On Dec 30, 2008, at 10:52 AM, Steve Cronin wrote:
You seem to be saying that I should have ALL the impacted methods
visible in my category declaration.
Don't 'hide' them by burying them inside -peformSelector().
Is that accurate?
Correct. It is sort of an either/or situation.
If you want to use -performSelector:, then the compiler will never
warn because there will be no expression that uses the method
declaration to warn about.
However, -performSelector: is slower and can hide problematic
invocations exactly because the compiler cannot validate the
argumentation to the method. As well, -performSelector: cannot be
used with non-object arguments. You couldn't pass an (NSRect)
parameter via -performSelector:, for example.
For those reasons, -performSelector: is not typically used. Instead,
you declare the method somewhere sensible and then simply invoke the
method after testing to see if the object responds to the selector.
For the delegation pattern, the declarations are hung off of NSObject
in the form of informal protocols (which are really just a category
@interface with no corresponding @implementation).
For example, NSTableView declares:
@interface NSObject(NSTableViewDelegate)
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell
forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:
(NSTableColumn *)tableColumn row:(NSInteger)row;
...
@end
And then used something like:
if ([delegate
respondsToSelector
:@selector(tableView:willDisplayCell:forTableColumn:row:)])
[delegate tableView: self willDisplayCell: cell forTableColumn: tc
row: 42]; // you get the idea...
This has several advantages. Primarily, it works -- neither of the
above methods could be used with -performSelector: variants. Also, it
is faster and the compiler validates the types of the arguments
properly.
Because the delegate can be an instance of *any* class, the
declaration off of NSObject is accurate.
If the methods you are interested in will *always* be implemented on
subclasses of a particular class, declare them in an informal protocol
of that class.
Alternatively, you could implement the methods in that class directly
as no-ops and then just always call 'em without testing via -
respondsToSelector:. This is commonly done when using an abstract
class and specific subclasses.
As an example, consider NSView. NSView implements -drawRect:, which
does absolutely nothing. But by implementing that method, then NSView
can call -drawRect: on subviews with impunity.
Is there no overhead at all for a category declaration?
Nope. None. An informal protocol declaration -- a category
declaration with no corresponding @implementation -- is only
considered at compile time. None of the information contained in the
informal protocol will survive through to the runtime.
b.bum
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden