Re: User interface validation doesn't work, right?
Re: User interface validation doesn't work, right?
- Subject: Re: User interface validation doesn't work, right?
- From: Bill Cheeseman <email@hidden>
- Date: Thu, 2 Jul 2009 13:52:09 -0400
On Jul 2, 2009, at 12:24 PM, Keary Suska wrote:
Because the two protocols in question are formal protocols, the
@interface declaration must specify conformance. If it doesn't, then
no assumption of conformance should be made. Pure and simple. Also,
protocol conformance is not inheritable in Objective-C.
1. Taking that last point first, the Objective-C 2.0 Programming
Language document says this: "A class is said to conform to a formal
protocol if it adopts the protocol or inherits from another class that
adopts it." I believe, without checking, that this was true in 1.0,
also. I take that to mean that protocol conformance is in fact
inherited. That makes sense, because a protocol is simply a promise
that certain methods are implemented, and implemented methods are
inherited by subclasses.
2. The key question for me is your first point.
The way I work around the lack of automatic validation for buttons is
this: In my window controller, I implement -validateUserInterfaceItem:
and declare that my controller conforms to the
NSUserInterfaceValidations protocol. That's exactly what NSDocument
does, as I understand it. Since user interface items are not
automatically validated, I force validation by implementing NSWindow's
-windowDidUpdate: delegate method so that it loops through all
subviews of the window calling my controller's -
validateUserInterfaceItem: protocol method. (I could use something
other than -windowDidUpdate: to trigger the protocol method if
efficiency becomes an issue, but at this point doing it every time the
window updates works just fine. I am aware that Apple is struggling
with efficiency concerns in automatic validation of toolbar items.)
Now here's my question for you: In my controller's implementation of -
validateUserInterfaceItem:, I can either limit the items that I enable/
disable by checking whether their class is NSButton (which I know
responds to -action and -setEnabled:, and I can confirm that
programmatically). Or, instead, I can limit the items by checking
whether they conform to the NSValidatedUserInterfaceItem protocol. If
I do the latter, I have to declare a subclass of NSButton and declare
that it conforms to the protocol because NSButton does not itself
declare conformance, and of course I have to set the type of my
buttons to my subclass type in Interface Builder. Either technique
works (I know because I've already done it), but testing for
compliance with the NSValidatedUserInterfaceItem protocol somehow
seems purer to me.
But then, as you point out, I am arrogating to myself the decision
whether NSButton conforms to the protocol. It clearly does, in my
view, because it inherits -action and -tag methods from NSControl, and
I know they work. Therefore I don't have to reimplement them in my
subclass of NSButton, although I am perfectly entitled under the rules
of the language to re-implement them myself if I choose to do so. If I
did re-implement them in my subclass, I would have every right to
declare that my subclass conforms to the protocol, because I own my
subclass. Implementing those two methods is all that conformance
requires. Objecting to this approach if I simply rely on inheriting
NSControl's implementations of -action and -tag seems like it's
elevating form over function. In other words, I view NSButton's
failure to declare conformance to be a bug.
Now, by my logic, NSControl also conforms, because that's where -
action and -tag are declared. But NSControl does not implement -
setEnabled:, so it wouldn't make any sense as a practical matter.
That's just another way of saying that the
NSValidatedUserInterfaceItem protocol is itself faulty, because it
does not promise that a conforming class can actually enable/disable
itself. (The problem is that different user controls that can be
enabled/disabled use methods with different signatures, such as
segmented controls. Therefore, to make my approach foolproof, I have
to check not only for an item's conformance to the protocol, but also
whether it responds to the -setEnabled: selector and any other
selector that I know enables/disables a user control I care about.)
Where would you come out on this question? From your comments, I
assume you would say I should not subclass NSButton and declare it as
conforming. Then I would have to simply check whether the class of an
item is the NSButton class. You might also insist that I should not
name my validation method -validateUserInterfaceItem:, but something
else such as -updateWindow, because I risk confusing people about what
my controller really does. In that case, I'm back where most Cocoa
applications were before Cocoa bindings were invented, declaring a
custom -updateWindow method and calling it from -windowDidUpdate or
whatever.
I would prefer to do things the NSUserInterfaceValidations way, so
that I'm ready when Apple gets around to making user interface item
validation automatic, which I really think it ought to do (with an on/
off switch). (Apple will probably say I should move on to Cocoa
Bindings and get over it.)
--
Bill Cheeseman
email@hidden
_______________________________________________
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