A version of the NSMenuItem swizzling to hide menu icons that properly handles palette menus (which have icons and no text))
NSMenuItem+IconHiding.swift edited
29 lines 982 B view raw
1extension NSMenuItem { 2 /// Disables all icons in all regular menu items. 3 /// 4 /// Call `NSMenuItem.disableIcons` early (from AppDelegate.init is good). 5 public static func disableIcons() { 6 let originalSelector = #selector(getter: image) 7 let nilImageSelector = #selector(returnNilInsteadOfImage) 8 9 guard 10 let originalMethod = class_getInstanceMethod(NSMenuItem.self, originalSelector), 11 let newMethod = class_getInstanceMethod(NSMenuItem.self, nilImageSelector) 12 else { 13 return 14 } 15 16 method_exchangeImplementations(originalMethod, newMethod) 17 } 18 19 @objc private func returnNilInsteadOfImage() -> NSImage? { 20 // In a palette menu, as appears for example in the "zoom" button of a window, 21 // we want the icons to appear because labels are hidden. 22 if let menu, case .palette = menu.presentationStyle { 23 // Because the method implementations are swapped, this will return the original image. 24 return self.returnNilInsteadOfImage() 25 } else { 26 return nil 27 } 28 } 29}