1

In my application I've subclassed the NSWindow and set the window level as 25. Since the window level is 25 the alert box and error dialog box were being hidden by the window.

Is there any chance to set the level of NSAlert

Marek H
  • 5,173
  • 3
  • 31
  • 42
user3748791
  • 31
  • 1
  • 5

2 Answers2

4

First of all. You shouldn't use magic numbers like 25.

There is a way to set window level but it's useless because runModal uses fixed windowLevel constant kCGModalPanelWindowLevel which is 8. You can verify it like this:

[self.window setLevel:25];
NSAlert *alert = [NSAlert alertWithMessageText:@"1" defaultButton:@"2" alternateButton:nil otherButton:nil informativeTextWithFormat:@"3"];
[alert runModal];

(lldb) po [alert.window valueForKey:@"level"]

8

#define NSModalPanelWindowLevel kCGModalPanelWindowLevel

Solution:

  1. Use sheet

    [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse response){ }];
    
  2. Swizzle implementation runModal with your own one.

  3. Recreate NSAlert functionality as a subclass of NSWindow/NSPanel (don't inherit NSAlert) and call showWindow: if you need to display it.

adev
  • 2,052
  • 1
  • 21
  • 33
Marek H
  • 5,173
  • 3
  • 31
  • 42
  • At what point does NSAlert set the window level, I wonder? Looking at your code snippet above, could one do [alert.window setLevel:whatever] just before [alert runModal]? If NSAlert sets up its window at construction, or lazily on demand, then that might work, but if runModal sets it, then no dice... – bhaller Sep 29 '15 at 12:05
  • runModals internal implementation will reset the window level so it's useless. If you want to have it above with less effort use max level 7. Otherwise you have to write some code. If you don't need modal behaviour you can also try to use showWindow on the internal window of nsalert. But you have to test it. Never used it that way. – Marek H Sep 29 '15 at 12:23
0

You can do this, but it's a pretty gross kludge. The trick is to run a bit of code after runModal has started and set the alert window's level. You do the following before calling runModal to re-set the level after NSAlert has.

dispatch_async(dispatch_get_main_queue(), ^{
    [[NSApp modalWindow] setLevel:myLevel];
});
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154