Possible Erratum in Menu Item Validation in Chapter 21


#1

In the following code:

override func validateMenuItem(menuItem: NSMenuItem) -> Bool { switch menuItem.action { case Selector("copy:"): return intValue == nil default: return super.validateMenuItem(menuItem) } }

I think the comparison should be not equals.

           return intValue != nil

Also, I have found that if the cases don’t cover every MenuItem that has a method implemented in the class, and everything it inherits from, the call to super.validateMenuItem(menuItem) in the default case fails at runtime. So in the example there needs to be cases for savePDF: print: , cut: and paste: also. The following code works for me:

override func validateMenuItem(menuItem: NSMenuItem) -> Bool { switch menuItem.action { case Selector("savePDF:"), Selector("cut:"), Selector("copy:"): return intValue != nil case Selector("paste:"): return true // Inherited method case Selector("print:"): return true default: return super.validateMenuItem(menuItem) } }

But then I thought about it some more and realised all this is doing is preventing the default case from being executed. Really the problem is with super.validateMenuItem(menuItem). I don’t think this method exists in any of the super classes of DiceView so I don’t think it should be called.

The best option is probably to have the default case return true, which seems to be how it was done in Objective-C.

override func validateMenuItem(menuItem: NSMenuItem) -> Bool { switch menuItem.action { case Selector("copy:"): return intValue != nil default: return true } }


#2

Thanks. This method is now a protocol method in Swift 4.2. So add the Protocol name “NSMenuItemValidation” to DieView (i.e. class DieView: NSView, NSMenuItemValidation { … }). You no longer use “override”, and as you said, make the corrections: return intValue != nil, and default: return true.

… However, after working on the 2nd challenge, for DieView, have realized that you need to add NSMenuItemValidation as a protocol for the DieView NSView, but for an NSDocument (in the RaiseMan example), it’s not necessary, just override the validateMenuItem method. Hope that helps. Cheers.