Previous Entry Share Next Entry
Cocoa Menu Validation
Cocoa supports automatic menu validation based on a few simple rules. However, it can be inconvenient to keep adding things to -validateMenuItem: all the time, particularly when there are inheritance hierarchies involved.

There's a pattern that can help you get it right much more easily using introspection. You can implement your -validateMenuItem: method to ask the receiver whether it can respond to a particular selector at the moment, like so:
- (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
    BOOL enabled = YES;
    SEL itemAction = [menuItem action];
    if (itemAction != nil) {
        if ([self respondsToSelector:itemAction]) {
            SEL canAction = [self canSelectorForAction:itemAction];
            if ((canAction != nil) && [self respondsToSelector:canAction]) {
                BOOL (*performCanAction)(id, SEL) = (BOOL (*)(id, SEL)) objc_msgSend;
                enabled = performCanAction(self, canAction);
            } else {
                enabled = YES;
    return enabled;

- (SEL)canSelectorForAction:(SEL)action
    NSString *actionString = NSStringFromSelector(action);
        // actionString is guaranteed to be 2+ characters
    NSString *actionStringFirst = [actionString substringToIndex:1];
    NSString *actionStringBody = [actionString substringWithRange:
        NSMakeRange(1, [actionString length] - 2)];
    NSString *canString
    = [[@"can" stringByAppendingString:[actionStringFirst uppercaseString]]
    return NSSelectorFromString(canString);
The above checks whether or not the receiver responds to the item's action selector. If it does, it will check if the receiver also implements a -(BOOL)canActionName selector, and use that to tell whether the menu item should be enabled.

The -canSelectorForAction: method just takes an action selector and returns its equivalent "canAction" selector, by upper-casing the first letter and appending it to "can". This lets you write a pair of methods for each action, one to perform the action and one to tell whether the action can be performed at the moment, leading to easy-to-test and uncluttered validation code.

Update (June 19, 2008): Changed how the -(BOOL)canActionName selector is performed to be safe and correct on Intel, and other architectures where a (BOOL) return might not be exactly equivalent to an (id) return. Thanks to an anonymous commenter for the correction!

  • 1

Compiler Warning

Thank you for the helpful hints for menu validation. After getting your code to work I looked into fixint the cast from pointer to integer of different size warning on the line where you call enabled = (BOOL) [self performSelector:canAction] . I found an article at which shows a way to fix this warning. I came to the following solution:

Add the following import: #import <objc/objc-runtime.h>
Replace: enabled = (BOOL) [self performSelector:canAction];
with: BOOL (*performCanAction)(id, SEL) = (BOOL (*)(id, SEL)) objc_msgSend;
enabled = performCanAction(self, canAction);

I know this is an old post, but I figured this suggestion might be helpful to anyone else who finds it.

Re: Compiler Warning

Thanks for the update! That's totally the right thing to do, I'll edit the post to fix it up and credit you.


I took your example and extended to do menu initialization as well which was pretty trivial given the nice work that you did on this example. I emailed you on since I wanted your permission to use your example in some public domain code. I would be happy to send it again.

check for responds to

i'm still a cocoa noob, so may be wrong, but i think i read that your object is first checked for respondsToSelector before validateMenuItem is even called so your call:

if ([self respondsToSelector:itemAction]) {

may be redundant??

owhowjor pjcp

ejoslcf fdc hqeaw fat mature ( mature.html)


vstft oynqon qkr orgy pics ( pics.html)

bgimelce psjc

ensm qosrf weight loss and calories ( jyeonc h la m xyc

tapw hmplk [URL=]weight loss and calories[/URL] vtrudz g ky r pdz

  • 1

Log in