Avevo una situazione simile in cui volevo disattivare condizionatamente alcune operazioni di annullamento/ripristino quando l'app si trova in uno stato specifico (pur consentendo di annullare/ripristinare le altre operazioni).
Il metodo di implementazione di - (BOOL)validateMenuItem:(NSMenuItem *)item
su una vista non funziona per me (ho un'app basata su documenti su 10.12). Per la documentazione in https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/MenuList/Articles/EnablingMenuItems.html:
Se c'è un oggetto nella catena risponditore che implementa l'azione del prodotto, NSMenu poi controlla se l'oggetto implementa il validateMenuItem: o validateUserInterfaceItem: metodo. In caso contrario, la voce di menu è abilitata. In tal caso, lo stato abilitato della voce di menu è determinato dal valore di ritorno del metodo.
La vista dovrebbe aggiungere un metodo di annullamento che fa anche la cosa giusta.
Quando ho sondato la catena risponditore, ho scoperto che la mia NSWindow era l'oggetto che ha risposto alla undo:
(anche se non è parte dell'interfaccia documentato), quindi il mio piano attuale è quello di utilizzare un NSWindow sottoclasse personalizzato con l'imeplementation di validateMenuItem
, lungo le linee di:
#import "Window.h"
@implementation SBXWindow
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag screen:(NSScreen *)screen
{
self = [super initWithContentRect:contentRect styleMask:style backing:bufferingType defer:flag screen:screen];
return self;
}
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
// Call super imeplementation as it appears to update the menu item title (and potentially other stuff)
BOOL result = [super validateMenuItem:item];
if (result == NO) {
return NO;
}
if (item.action == @selector(undo:) || item.action == @selector(redo:)) {
// Add custom logic here
}
return result;
}
@end
Tuttavia ci sono avvertimenti che i undo:
redo:
metodi non sono implementati. Questi possono essere eliminati con la creazione di una categoria NSWindow, come ad esempio:
@interface NSWindow (SBXUndoable)
- (void)undo:(id)sender;
- (void)redo:(id)sender;
@end
Non so se ci sono dei problemi nel fare questo (non ho notato alcuna), ma lo fa eliminare gli avvertimenti. Da allora ho cambiato la classe in una classe Swift, che non aveva alcun avvertimento da affrontare.
Sì. Questo è stato. Dovuto implementare (IBAction) annullare: (id) mittente però. – Sebastian