NSAlert in a command line application

We encounter following GUI issue on Mac OSX 10.11 Beta 8 (build 15A279b)

With Xcode 7, in a project targeting OSX 10.8, 10.9, 10.10 and 10.11, we create a command line tool application. In the application main function, we create a NSAlert object with an OK button and use the runModal method to display it. When we run this application:

  • On OSX 10.11, the alert is displayed as expected, but when clicking the OK button, the alert stays displayed until the application itself quits. Moreover, if we try to display a second alert, the previous one disappears and the new one stays displayed after we have clicked the OK button.
  • On OS X 10.8, 10.9 or 10.10, when clicking the OK button, the alert is properly closed as expected.


The project has been built with Xcode 7, but occurs with Xcode 6.4 as well.

Is that a known issue ? How can we recover the behaviour of previous versions on OS X 10.11 ?


---------------

Sample code to reproduce the issue:


#import <Foundation/Foundation.h>

#import <Cocoa/Cocoa.h>


int main(int argc, const char * argv[]) {


/

@autoreleasepool {

NSAlert* msgBox1 = [[NSAlert alloc] init];

[msgBox1 setMessageText: @"Welcome !"];

[msgBox1 addButtonWithTitle : @"OK"];

[msgBox1 runModal];

}

int c=0;


/ On OSX 10.11: msgBox1 stays displayed when clicking the OK button


printf(" --------- Hit a key to display a second alert ----------\n");

c=getchar();


/

@autoreleasepool {

NSAlert* msgBox2 = [[NSAlert alloc] init];

[msgBox2 setMessageText: @"Welcome !"];

[msgBox2 addButtonWithTitle : @"OK"];

[msgBox2 runModal];

}


/

/


printf(" --------- Hit a key to exit ----------\n");

c=getchar();

return 0;


/

}

Replies

I'm seeing a simular issue - in certain situations we display an NSAlert using runModal before we create any application windows. Clicking either button (Yes or No) will keep the alert visible until the application has shut down. This behavior is displayed using Xcode 7 on 10.11, but not on 10.7 - 10.10.


Have you figured out a solution?

I had this same problem and struggled for a long time trying to find a way to make the dismissed alerts disappear.


My solution was to forsake NSAlert altogether in favor of CFUserNotificationNotice. That API (https://developer.apple.com/documentation/corefoundation/1534478-cfusernotificationdisplaynotice?language=objc) or the CFUserNotificationAlert API (https://developer.apple.com/documentation/corefoundation/1534496-cfusernotificationdisplayalert?language=objc) can be used to display stand-alone alert dialogs which are identical to those produced by NSAlert, but they can be dismissed unlike NSAlert when run from a simple windowless binary.


Here is a link to an example of CFUserNotificationDisplayAlert: http://macosx-programming.blogspot.com/2011/09/heres-sample-to-display-messagebox-with.html


And here is a sample of my solution with CFUserNotificationDisplayNotice which displays alerts when they are posted to a pasteboard:


-----

#import <Foundation/Foundation.h>

#import <CoreFoundation/CoreFoundation.h>

#import <AppKit/Appkit.h>

/*

Uses an NSPasteboard called textEditBoard to listen for messages from textEditPlugin

*/


int main(void) {

NSPasteboard *pb = [NSPasteboard pasteboardWithName:@"MyBoard"];

@try {

while(true) {

if ([pb canReadObjectForClasses:@[[NSString class]] options:nil]) {

NSArray *contents = [pb readObjectsForClasses:@[[NSString class]] options: nil];

CFStringRef msg = (__bridge CFStringRef) [contents firstObject];

[pb clearContents];


CFUserNotificationDisplayNotice(2, 3, NULL, NULL, NULL, CFSTR("ALERT"), msg, CFSTR("OK!")

);

//fprintf(stdout, "%s\n", [msg UTF8String]);

}

}

} @finally {

[pb release];

return 0;

}

return 0;

}