NSAlert won't disappear - objective-c

I'm using a simple NSAlert based on Apple's sample code, and while it displays fine, it never disappears.
Code:
void DisplayAlert()
{
NSAlert *alert = [[NSAlert alloc] init];
NSLog(#"TEST");
[alert addButtonWithTitle:#"OK"];
[alert setMessageText:#"Yay!"];
[alert setInformativeText:#"This is an informational alert."];
[alert setAlertStyle:NSAlertStyleInformational];
[alert runModal];
NSLog(#"TEST2");
[alert.window close];
[alert release];
NSLog(#"TEST3");
}
I have tried with and without the [alert.window close] line and neither way will the alert disappear.
I have also tried making the first line [[[NSAlert alloc] init] autorelease]; but that did not help, either.
All of the NSLog messages appear.

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 CFUserNotificationAlert. This blocking alert API or the non-blocking CFUserNotificationNotice API can be used to display stand-alone alert dialogs which are identical to those produced by NSAlert, but they can be dismissed unlike NSAlert dialogs when run from a simple windowless binary.
Here's an example of CFUserNotificationDisplayAlert and a preview of some of its code below:
#import <CoreFoundation/CoreFoundation.h>
int main(void) {
CFOptionFlags cfRes;
//display alert with 5 second timeout, at NoteAlertLevel
CFUserNotificationDisplayAlert(5, kCFUserNotificationNoteAlertLevel,
NULL, NULL, NULL,
CFSTR("Testing"),
CFSTR("Click on any button..."),
CFSTR("OK"),
CFSTR("Cancel"),
CFSTR("Test Button"),
&cfRes);
return cfRes;
}

The method you need is -orderOut: not -close. Alert/Panel windows are not documents and are not "closed" in the usually sense. You just what them to disappear.

Related

Stop NSPopover from closing if NSAlert dialog appears?

Hi I have a NSStatusItem that shows a popover when clicked. One option in the popover is to delete something; at this point I ask the user if they are sure.
The problem is that the Popover automatically closes as soon as the Alert appears.
I have tried all the different behavior settings like NSPopoverBehaviorSemitransient, NSPopoverBehaviorTransient and NSPopoverBehaviorApplicationDefined to no avail.
I also try catching it in - (BOOL)popoverShouldClose:(NSPopover *)popover but this isn't called when NSAlert appears.
Nothing seems to stop an NSAlert from closing a popover.
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:#"OK"];
[alert addButtonWithTitle:#"Cancel"];
[alert setMessageText:msg];
[alert setInformativeText:#"Warning, delete this folder?"];
[alert setAlertStyle:NSCriticalAlertStyle];
// Show the alert
if ([alert runModal] == NSAlertFirstButtonReturn) {
I also tried showing the alert as a sheet in the popover which kind of works but then the popover stays around no matter if I click outside it.

How to disable all drag-and-drop operations when NSAlert is shown as modal window

I have NSWindow with custom NSView. This custom NSView override performDragOperation method. Drag-and-drop operations works good. But when I create and show NSAlert as modal window I need block drag-and-drop, method, performDragOperation shouldn't be called.
NSAlert *alert = [[NSAlert alloc]init];
[alert addButtonWithTitle:#"Excellent"];
[alert setMessageText:#"This is your message."];
[alert runModal];
One of possible solution is add code that verify if dialog is shown to performDragOperation method. But how to detect if NSAlert is shown.
For example for sheet I can use:
if([window attachedSheet]) {
...
}
But how do this for
[alert runModal];
According to Willeke comments, to detect if some Alert is running can be used next code:
if([NSApp modalWindow]) {
...
}

How to gather input from an alert when a window is closed to determine whether to save in an objective-c mac application?

I made it so that in an objective-c mac application developed in Xcode, an alert would appear asking the user whether they wish to save when they try and close the main window. How would I gather the user's input from this alert?
I know you can use this code to generate an alert with various options and text:
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:#"Save and Quit"];
[alert addButtonWithTitle:#"Quit"];
[alert setMessageText:#"Would you like to save before you quit?"];
[alert setInformativeText:#"You are about to quit. Would you like to save your progress?"];
[alert setAlertStyle:NSWarningAlertStyle];
[alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:#selector(null) contextInfo:nil];
And I know that you can use the
- (void)windowWillClose:(NSNotification *)notification
method to run when the main window is closed, but how would I gather the user's input from this alert?
NSAlert panels aren't really meant for gathering info but for alerting the user of some sort of state and then recording which button they pressed in response.
What I've had to do in the past is to create my own window/xib with it's window controller, textviews, and selectors and manage it all from there.
On the other hand if you were just talking about getting the state of which button was pressed, as shown from the link, something like this would work:
if ([alert runModal] == NSAlertFirstButtonReturn) {
// OK clicked, delete the record
[self deleteRecord:currentRec];
}

App crashes when using AHAlertView project

I'm trying to display a custom UIAlertView and I'm using AHAlertView:
https://github.com/warrenm/AHAlertView
I added both AHAlertView.m and .h to my project and add the following to the viewDidLoad method:
NSString *title = #"Alert View Title";
NSString *message = #"This is a message that might prompt you to do something.";
AHAlertView *alert = [[AHAlertView alloc] initWithTitle:title message:message];
__weak AHAlertView *weakAlert = alert;
[alert setCancelButtonTitle:#"Cancel" block:^{
weakAlert.dismissalStyle = AHAlertViewDismissalStyleTumble;
}];
[alert addButtonWithTitle:#"OK" block:^{
weakAlert.dismissalStyle = AHAlertViewDismissalStyleZoomDown;
}];
[alert show];
The problem is when I'm tapping either one of the buttons, the app crashes with:
"Application windows are expected to have a root view controller at the end of application launch"
I don't know what I did wrong, I looked at the sample project and this is the way the alert is being used.
How can I implement it correctly?
Did you activate -fno-objc-arc option ? If you did, deactivate it, AHAlertView support ARC

Why UIAlertView prevents my modal view controller from being displayed?

Let's say that when the user presses a button a message needs to be shown and then a modal view controller is displayed.
I would write something like that :
- (void)pickImageButtonPressed:(id)button {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert"
message:#"Some alert"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[[UIApplication sharedApplication].keyWindow.rootViewController
presentModalViewController:picker animated:YES];
[picker release];
}
With this code, the modal view controller is simply not displayed !
However, if I switch the two blocks of code (show modal first, then show the alert), the view controller is displayed modally and the alert shows up above it, exactly as I want.
My question is: why the alert prevents the modal view controller from being displayed ?
Please note that I do not want to wait for alert to be dismissed before calling presentModalViewController.
Update :
I figured out that my production code was a bit more complicated than what I first put. I updated the example code and then finally found a simple example to reproduce the problem.
Note that in my production code, the popup is displayed from a place where I don't have any reference to a view controller, that's why I use [UIApplication sharedApplication].keyWindow.rootViewController instead of a direct reference to a view controller
I finally found the answer. The issue really was on this line:
[[UIApplication sharedApplication].keyWindow.rootViewController
presentModalViewController:picker animated:YES];
When an alert is displayed, [UIApplication sharedApplication].keyWindow.rootViewController is nil !. That's why the picker was never displayed. And that's why it worked when I switched the two blocks.
Now I need to find a way to get the most relevant view controller to present the picker modally...