Question

I'm trying to implement a feature to password protect my cocoa app. So in my AppDelegate, if password is entered correctly on a window, I'll bring up the main app window by calling NSApp runModelforWindow method.

it works fine, except, in the preferences I do allow user to change the password. So which means in order to prevent hacking from users, I'll have to hide the main menu, until password is entered correctly.

I don't want to remove certain menu items by using removeItemAtIndex or programmatically set the target action to call the method to bring up the preference window. Instead, I would like to temporary hide the [NSApp mainMenu]. I searched for it and can't seem to find any method, like setHidden:YES in order to hide it.

I have tried [[NSApp mainMenu] cancelTracking] but it doesn't do the job

is there any easy way to do this?

Was it helpful?

Solution

You can use the -setPresentationOptions: method on NSApp to hide and show many parts of the standard OS UI, including the menu bar and Dock. Note that you must hide both the menu bar and Dock together:

/* Hide */
[NSApp setPresentationOptions:[NSApp presentationOptions] |
                               NSApplicationPresentationHideMenuBar |
                               NSApplicationPresentationHideDock];

/* Show */
[NSApp setPresentationOptions:[NSApp presentationOptions] ^
                               NSApplicationPresentationHideMenuBar ^ 
                               NSApplicationPresentationHideDock];

This is a pretty disruptive UI experience though. Consider just disabling any menu items or UI elements that you don't want the user to access while the password dialog is on screen.

OTHER TIPS

Unfortunately, there is no easy way to hide the main menu - it is always shown, or always hidden (depending on info.plist flag). As well as Dock icon. See LSUIElement for this. There is a trick to show this menu when it is initially hidden, but there is no good way to hide/show it in runtime.

If you're serious about protecting (usage of) your application with a password , hiding the menubar won't help much, as you already concluded.

To prevent anonymous users from performing actions that require authentication, you will actually need to create logic in your code for protecting these actions and checking if the user did in fact authenticate correctly, each time they try do something (select a menuitem or press a button).

Having said that, you can prevent anonymous users from for instance opening the preference-window by disabling the related menu-item. Personally I would much prefer actually disabling the relevant controls in the preference-window, so users can explore the different options, but also understand that they need to authenticate. You could follow the model Apple used for the macOS System Preferences window, which will lock many (but not all) Preference Panes, depending on the particular Pane, and whether or not the user did authenticate.

A good starting-point would probably be the relevant documentation on Apple's developer website. For instance: https://developer.apple.com/documentation/securityfoundation

And if you still just need want to hide the menubar, you can always just do:

[NSMenu setMenuBarVisible:(BOOL)onOff];

But I believe it's better to use the solution from @jatoben's answer, as NSApplication's presentationOptions because this allows you to really disable functionalirty. Just hiding the menubar with [NSMenu setMenuBarVisible:(BOOL)onOff] does not disable shortcuts for the menuItems, so you still could show the preference-window using ⌘,.

On a sidenote, I believe you would save yourself all this trouble if you would simply show your password-dialog using

NSModalSession session = [NSApp beginModalSessionForWindow:passwordDialog];
[NSApp runModalSession:session];

This shows you dialog modally for the application, meaning that all other windows and also almost all menuitems are automatically disabled…

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top