Dismissing UIAlertViews when entering background state
Asked Answered
B

12

31

Apple recommends dismissing any UIAlertViews/UIActionSheets when entering background state in iOS 4. This is to avoid any confusion on the user's part when he relaunches the application later. I wonder how I could elegantly dismiss all UIAlertViews at once, without retaining a reference to it everytime I set one up...

Any idea ?

Biomedicine answered 23/6, 2010 at 22:18 Comment(0)
T
24

I was intrigued by Dad's answer (funny username :), and curious why it was down-voted.

So I tried it.

Here is the .m part of a subclass of UIAlertView.

Edit: (Cédric) I have added a way to catch calls to delegate methods and remove the observer then to avoid multiple registrations to the notification center.

Everything bundled in a class in this github repo: https://github.com/sdarlington/WSLViewAutoDismiss



    #import "UIAlertViewAutoDismiss.h"
    #import <objc/runtime.h>

    @interface UIAlertViewAutoDismiss () <UIAlertViewDelegate> {
        id<UIAlertViewDelegate> __unsafe_unretained privateDelegate;
    }
    @end

    @implementation UIAlertViewAutoDismiss

    - (id)initWithTitle:(NSString *)title
                message:(NSString *)message
               delegate:(id)delegate
      cancelButtonTitle:(NSString *)cancelButtonTitle
      otherButtonTitles:(NSString *)otherButtonTitles, ...
    {
        self = [super initWithTitle:title
                            message:message
                           delegate:self
                  cancelButtonTitle:cancelButtonTitle
                  otherButtonTitles:nil, nil];

        if (self) {
            va_list args;
            va_start(args, otherButtonTitles);
            for (NSString *anOtherButtonTitle = otherButtonTitles; anOtherButtonTitle != nil; anOtherButtonTitle = va_arg(args, NSString *)) {
                [self addButtonWithTitle:anOtherButtonTitle];
            }
            privateDelegate = delegate;
        }
        return self;
    }

    - (void)dealloc
    {
        privateDelegate = nil;
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
        [super dealloc];
    }

    - (void)setDelegate:(id)delegate
    {
        privateDelegate = delegate;
    }

    - (id)delegate
    {
        return privateDelegate;
    }

    - (void)show
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationDidEnterBackground:)
                                                     name:UIApplicationDidEnterBackgroundNotification
                                                   object:nil];

        [super show];
    }

    - (void)applicationDidEnterBackground:(NSNotification *)notification
    {
        [super dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:NO];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
    }

    #pragma mark - UIAlertViewDelegate

    // The code below avoids to re-implement all protocol methods to forward to the real delegate.

    - (id)forwardingTargetForSelector:(SEL)aSelector
    {
        struct objc_method_description hasMethod = protocol_getMethodDescription(@protocol(UIAlertViewDelegate), aSelector, NO, YES);
        if (hasMethod.name != NULL) {
            // The method is that of the UIAlertViewDelegate.

            if (aSelector == @selector(alertView:didDismissWithButtonIndex:) ||
                aSelector == @selector(alertView:clickedButtonAtIndex:))
            {
                [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                name:UIApplicationDidEnterBackgroundNotification
                                                              object:nil];
            }
            return privateDelegate;
        }
        else {
            return [super forwardingTargetForSelector:aSelector];
        }
    }

    @end

It works nicely. It's great, because you can just start using it the same way that you used to use UIAlertView.

I haven't had time to test it thoroughly, but I didn't notice any side effect.

Treadmill answered 5/7, 2010 at 17:31 Comment(16)
The only change I would make is to register the observer in the show method instead of init.Procrustes
@Gotosleep good point, it would avoid to call - dismissWithClickedButtonIndex: animated: on an not visible alert. Don't think it's a problem at the moment, but will be better for future compatibility. In this case, make sure that removing an observer not registered is ok, or better, adapt the code to avoid it.Treadmill
The Problem with this answer is that you will receive the applicationWillResignActive notification also when you are just receiving an SMS which you dismiss. Then you are back in your application and NOT in the background, but you dismissed your alert already. I do not think that this is properly handled. Take a look at the graphik I posted as a link in my answer below.Zinazinah
Btw, this is a nice example for using the new block syntax instead of the badly named applicationWillResignActive method. Why do you define if with the sender and do not use it? I think this code is not well designed, both in how it is implemented and also conceptionally.Zinazinah
@Zinazinah You're correct. I edited the answer to register to the proper notification. Nice workflow graphic!Treadmill
@Treadmill I think it is Apple's fault. They claim you used compile against iOS4 and everything works out of the box. But it does not. One has to really think how to manage the state of the application as there are new entry points now.Zinazinah
@Zinazinah Regarding your second comment, I do not understand your question "Why do you define if with the sender and do not use it?". What do you mean? Regarding the code design and implementation quality: I spend time on SO to learn and improve myself. Always appreciate to get feedback. What do you think is wrong in this code? Seems good to me. What would you change?Treadmill
@Treadmill My question was if a function has an argument, such as your - (void) applicationDidEnterBackground:(id) sender, the you usually do something with the argument in this case "sender" in the function, which you do not. I was just wondering why it is there. BTW if you like that graphic, feel free to upvote the answer ...Zinazinah
@Treadmill Regarding the block syntax: your code could look like this: [[NSNotificationCenter defaultCenter] addObserverForName: UIApplicationDidEnterBackgroundNotification object:self queue:nil usingBlock:^{[self dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:NO];}]; Notice that I am not using a string like you do, but instead a static string defined by UIKit. This way you avoid typos and typing as it is auto-completed by Xcode.Zinazinah
In case anyone want to use code like this, I have created a repository on github that implements it and the equivalent for UIActionSheet: github.com/sdarlington/UIViewAutoDismissCrist
@GorillaPatch: the reason for the sender parameter is that it is required by the NSNotificationCenter class, the selector for an observer must have 1 parameter, even though it is not needed here. However, it is misleading to type/name it "(id)sender" because it is actually a NSNotification*.Bracey
Before you use this, I would warn you to check Apple's documentation - where it mentioned "The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified." You app might either get rejected or does not work properly in the future.Naivete
This worked well for me, however I was able to simplify it. Remove everything except for dealloc, show, and applicationDidEnterBackground: methods. Remove privateDelegate and leave the caller to define the delegate. The UIAlertView object is registered for the notification in show and deregistered in dealloc. Everything works perfectly for me. The only problem I could see is if you were to hold on to your UIAlertView references for much longer than it is visible.Hierophant
the private delegate from Cédric does not work. just use dealloc to remove the observer. I've tested that and it works just find. The private delegate the was added doesn't actually cause the superclass to call the methods on the delegatePreclude
@StephenDarlington the link to github in your comment is broken. I added the fixed link in the answer.Treadmill
@Treadmill Thanks. GitHub say that they redirect when you rename repositories... I guess that doesn't always work!Crist
V
26

My call would be to add a category to UIAlertview adding the following function :

- (void) hide {
  [self dismissWithClickedButtonIndex:0 animated:YES];
}

And to suscribe to UIApplicationWillResignActiveNotification :

[[NSNotificationCenter defaultCenter] addObserver:alertView selector:@selector(hide) name:@"UIApplicationWillResignActiveNotification" object:nil];
Vladivostok answered 5/7, 2010 at 15:54 Comment(3)
Thanks this gives me a good idea on how to achieve what I want. I'll probably add two methods in a category - (void) showAndHidAutomatically, which will register itself and call show, upon the notification will call another method called hideAndUnregister, which will do just that. Enjoy your bounty reward :-)Undersized
I did some modifications: [[NSNotificationCenter defaultCenter] addObserver:alert selector:@selector(hide) name:UIApplicationDidEnterBackgroundNotification object:nil];Oxheart
I have a question. I have removed an observer in hide-method. It's fine. But how remove observer if AlertView closed by user (method "hide" didn't invoked)? In NoificationCenter stored a dead reference on dismissed AlertView?Hyperion
T
24

I was intrigued by Dad's answer (funny username :), and curious why it was down-voted.

So I tried it.

Here is the .m part of a subclass of UIAlertView.

Edit: (Cédric) I have added a way to catch calls to delegate methods and remove the observer then to avoid multiple registrations to the notification center.

Everything bundled in a class in this github repo: https://github.com/sdarlington/WSLViewAutoDismiss



    #import "UIAlertViewAutoDismiss.h"
    #import <objc/runtime.h>

    @interface UIAlertViewAutoDismiss () <UIAlertViewDelegate> {
        id<UIAlertViewDelegate> __unsafe_unretained privateDelegate;
    }
    @end

    @implementation UIAlertViewAutoDismiss

    - (id)initWithTitle:(NSString *)title
                message:(NSString *)message
               delegate:(id)delegate
      cancelButtonTitle:(NSString *)cancelButtonTitle
      otherButtonTitles:(NSString *)otherButtonTitles, ...
    {
        self = [super initWithTitle:title
                            message:message
                           delegate:self
                  cancelButtonTitle:cancelButtonTitle
                  otherButtonTitles:nil, nil];

        if (self) {
            va_list args;
            va_start(args, otherButtonTitles);
            for (NSString *anOtherButtonTitle = otherButtonTitles; anOtherButtonTitle != nil; anOtherButtonTitle = va_arg(args, NSString *)) {
                [self addButtonWithTitle:anOtherButtonTitle];
            }
            privateDelegate = delegate;
        }
        return self;
    }

    - (void)dealloc
    {
        privateDelegate = nil;
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
        [super dealloc];
    }

    - (void)setDelegate:(id)delegate
    {
        privateDelegate = delegate;
    }

    - (id)delegate
    {
        return privateDelegate;
    }

    - (void)show
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationDidEnterBackground:)
                                                     name:UIApplicationDidEnterBackgroundNotification
                                                   object:nil];

        [super show];
    }

    - (void)applicationDidEnterBackground:(NSNotification *)notification
    {
        [super dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:NO];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
    }

    #pragma mark - UIAlertViewDelegate

    // The code below avoids to re-implement all protocol methods to forward to the real delegate.

    - (id)forwardingTargetForSelector:(SEL)aSelector
    {
        struct objc_method_description hasMethod = protocol_getMethodDescription(@protocol(UIAlertViewDelegate), aSelector, NO, YES);
        if (hasMethod.name != NULL) {
            // The method is that of the UIAlertViewDelegate.

            if (aSelector == @selector(alertView:didDismissWithButtonIndex:) ||
                aSelector == @selector(alertView:clickedButtonAtIndex:))
            {
                [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                name:UIApplicationDidEnterBackgroundNotification
                                                              object:nil];
            }
            return privateDelegate;
        }
        else {
            return [super forwardingTargetForSelector:aSelector];
        }
    }

    @end

It works nicely. It's great, because you can just start using it the same way that you used to use UIAlertView.

I haven't had time to test it thoroughly, but I didn't notice any side effect.

Treadmill answered 5/7, 2010 at 17:31 Comment(16)
The only change I would make is to register the observer in the show method instead of init.Procrustes
@Gotosleep good point, it would avoid to call - dismissWithClickedButtonIndex: animated: on an not visible alert. Don't think it's a problem at the moment, but will be better for future compatibility. In this case, make sure that removing an observer not registered is ok, or better, adapt the code to avoid it.Treadmill
The Problem with this answer is that you will receive the applicationWillResignActive notification also when you are just receiving an SMS which you dismiss. Then you are back in your application and NOT in the background, but you dismissed your alert already. I do not think that this is properly handled. Take a look at the graphik I posted as a link in my answer below.Zinazinah
Btw, this is a nice example for using the new block syntax instead of the badly named applicationWillResignActive method. Why do you define if with the sender and do not use it? I think this code is not well designed, both in how it is implemented and also conceptionally.Zinazinah
@Zinazinah You're correct. I edited the answer to register to the proper notification. Nice workflow graphic!Treadmill
@Treadmill I think it is Apple's fault. They claim you used compile against iOS4 and everything works out of the box. But it does not. One has to really think how to manage the state of the application as there are new entry points now.Zinazinah
@Zinazinah Regarding your second comment, I do not understand your question "Why do you define if with the sender and do not use it?". What do you mean? Regarding the code design and implementation quality: I spend time on SO to learn and improve myself. Always appreciate to get feedback. What do you think is wrong in this code? Seems good to me. What would you change?Treadmill
@Treadmill My question was if a function has an argument, such as your - (void) applicationDidEnterBackground:(id) sender, the you usually do something with the argument in this case "sender" in the function, which you do not. I was just wondering why it is there. BTW if you like that graphic, feel free to upvote the answer ...Zinazinah
@Treadmill Regarding the block syntax: your code could look like this: [[NSNotificationCenter defaultCenter] addObserverForName: UIApplicationDidEnterBackgroundNotification object:self queue:nil usingBlock:^{[self dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:NO];}]; Notice that I am not using a string like you do, but instead a static string defined by UIKit. This way you avoid typos and typing as it is auto-completed by Xcode.Zinazinah
In case anyone want to use code like this, I have created a repository on github that implements it and the equivalent for UIActionSheet: github.com/sdarlington/UIViewAutoDismissCrist
@GorillaPatch: the reason for the sender parameter is that it is required by the NSNotificationCenter class, the selector for an observer must have 1 parameter, even though it is not needed here. However, it is misleading to type/name it "(id)sender" because it is actually a NSNotification*.Bracey
Before you use this, I would warn you to check Apple's documentation - where it mentioned "The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified." You app might either get rejected or does not work properly in the future.Naivete
This worked well for me, however I was able to simplify it. Remove everything except for dealloc, show, and applicationDidEnterBackground: methods. Remove privateDelegate and leave the caller to define the delegate. The UIAlertView object is registered for the notification in show and deregistered in dealloc. Everything works perfectly for me. The only problem I could see is if you were to hold on to your UIAlertView references for much longer than it is visible.Hierophant
the private delegate from Cédric does not work. just use dealloc to remove the observer. I've tested that and it works just find. The private delegate the was added doesn't actually cause the superclass to call the methods on the delegatePreclude
@StephenDarlington the link to github in your comment is broken. I added the fixed link in the answer.Treadmill
@Treadmill Thanks. GitHub say that they redirect when you rename repositories... I guess that doesn't always work!Crist
D
18

A totally different approach is a recursive search.

Recursive function for your application delegate

- (void)checkViews:(NSArray *)subviews {
    Class AVClass = [UIAlertView class];
    Class ASClass = [UIActionSheet class];
    for (UIView * subview in subviews){
        if ([subview isKindOfClass:AVClass]){
            [(UIAlertView *)subview dismissWithClickedButtonIndex:[(UIAlertView *)subview cancelButtonIndex] animated:NO];
        } else if ([subview isKindOfClass:ASClass]){
            [(UIActionSheet *)subview dismissWithClickedButtonIndex:[(UIActionSheet *)subview cancelButtonIndex] animated:NO];
        } else {
            [self checkViews:subview.subviews];
        }
    }
}

Calling it from the applicationDidEnterBackground procedure

[self checkViews:application.windows];
Dovekie answered 1/2, 2011 at 6:8 Comment(3)
Worked great for me. I did refactor it into two UIView category methods, though. - (void)dismissActionSheetsSubviews:(BOOL)animated and - (void)dismissAlertViewSubviews:(BOOL)animated {.Bod
This unfortunately no longer works in iOS7 because UIalertviews are no longer subviews of one of the application's windowsWyler
@fibnochi: please make a new answer out of your edit or use a comment. It really makes no sense to change the original post in such a drastic way. Thanks!Statis
C
12

huh. Haven't tried this yet, but I wonder if it would make sense to create a subclass of UIAlertView that listens for this Notification and closes itself if so...

That'd have the "automatically" without retaining / keeping it around characteristic OP is requesting. Make sure to unregister for the notification on close (else boom!)

Chronicles answered 1/7, 2010 at 7:20 Comment(2)
"Bravo!" to Guillaume for taking the time to write the test code I didn't have time to write. #3106474 Glad it worked as I'd imagined it would. Seems like a pretty clean and complete answer to the problem to me. Elegant even (?), if I do say so myself :-?Chronicles
This is an elegant solution. It shows an appreciation for the strengths of Objective-C.Abash
A
12

As someone mentioned in a comment: the accepted answer isn't the best/cleanest one since iOS 4.0 when we have blocks! Here's how I do it:

UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Alert!" message:@"This alert will dismiss when application resigns active!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification){
        [alert dismissWithClickedButtonIndex:0 animated:NO];
    }];
Allaround answered 17/1, 2014 at 7:26 Comment(4)
I'm wondering why this answer isn't upvoted more. It works really well and is very simple. Is this a poor solution and I'm not seeing why?Pressing
I'm not sure, but should the observer be removed when the alert is dismissed?Delldella
The reason why this isn't upvoted more is because, you have to do this to every alertview you show in your app. Some apps present many many UIAlertViews and it would be tedious to go around doing this everywhere.Angola
@Angola That's when you take advantage of CLANG and create a shortcut like [alert showWithAutoDismiss]; where showWithAutoDismiss is all defined with the above logic in one CLANG declaration. :DBrickyard
R
8

UIAlertView was deprecated in iOS 8 in favor of the UIAlertController. Unfortunately, this proves to be a tricky problem because the accepted solution won't work, as Apple explicitly doesn't support subclassing UIAlertController:

The UIAlertController class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

My solution is to simply traverse the view controller tree and dismiss all UIAlertControllers that you find. You can enable this globally by creating an extension of UIApplication and then calling it in the AppDelegate applicationDidEnterBackground method.

Try this (in Swift):

extension UIApplication
{
    class func dismissOpenAlerts(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController)
    {
        //If it's an alert, dismiss it
        if let alertController = base as? UIAlertController
        {
            alertController.dismissViewControllerAnimated(false, completion: nil)
        }

        //Check all children
        if base != nil
        {
            for controller in base!.childViewControllers
            {
                if let alertController = controller as? UIAlertController
                {
                    alertController.dismissViewControllerAnimated(false, completion: nil)
                }
            }
        }

        //Traverse the view controller tree
        if let nav = base as? UINavigationController
        {
           dismissOpenAlerts(nav.visibleViewController)
        }
        else if let tab = base as? UITabBarController, let selected = tab.selectedViewController
        {
           dismissOpenAlerts(selected)
        }
        else if let presented = base?.presentedViewController
        {
           dismissOpenAlerts(presented)
        }
    }
}

And then in your AppDelegate:

func applicationDidEnterBackground(application: UIApplication)
{
    UIApplication.dismissOpenAlerts()
}
Rolypoly answered 7/1, 2016 at 22:16 Comment(2)
I might be missing something at the first glance, but is there any reason why this recursive function should be returning UIViewController?Platonic
@AndriyGordiychuk Good call, I made this by porting another method I wrote to get the top-most view controller, but forgot to remove the return. Updated, thanks.Rolypoly
S
7

I Have had solved this with the following code:

/* taken from the post above (Cédric)*/
- (void)checkViews:(NSArray *)subviews {
    Class AVClass = [UIAlertView class];
    Class ASClass = [UIActionSheet class];
    for (UIView * subview in subviews){
        NSLog(@"Class %@", [subview class]);
        if ([subview isKindOfClass:AVClass]){
            [(UIAlertView *)subview dismissWithClickedButtonIndex:[(UIAlertView *)subview cancelButtonIndex] animated:NO];
        } else if ([subview isKindOfClass:ASClass]){
            [(UIActionSheet *)subview dismissWithClickedButtonIndex:[(UIActionSheet *)subview cancelButtonIndex] animated:NO];
        } else {
            [self checkViews:subview.subviews];
        }
    }
}



/*go to background delegate*/
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        NSArray* subviews = window.subviews;
        [self checkViews:subviews];
    }
}
Savitt answered 19/10, 2012 at 14:10 Comment(2)
This unfortunately no longer works in iOS7, because UIAlertViews cannot be found as a subview of an application windowWyler
Did somebody come with a nice solution for iOS7?Regimen
Z
3

The straightforward way is to hold a reference to the UIAlertView so you can dismiss it. Of course as petert mentioned you can do it with a Notification or use the delegate method on UIApplication

applicationWillResignActive:

does not always mean that you are going to the background. You will for example also receive that delegate call and notification (you get both) when the user gets a phone call or receives and SMS. So you have to decide what should happen if the user gets an SMS and presses cancel to stay in your app. You maybe want to make sure that your UIAlertView is still there.

So I would dismiss the UIAlertView and save the state in the delegate call when you really go into the background:

applicationDidEnterBackground:

Have a look at Session 105 - Adopting Multitasking on iOS4 of WWDC10 available for free at developer.apple.com. It gets interesting at 16:00 min

Check out this graphic to understand the different states of an application

Zinazinah answered 5/7, 2010 at 7:26 Comment(0)
J
1

I have this on my TODO list, but my first instinct would be to listen out for the notifcation UIApplicationWillResignActiveNotification (see UIApplication) in the views where you have things like UIAlertView - here you can programmatically remove the alert view with:

(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated

The discussion for this method even suggests what it's for in iOS4!

In iPhone OS 4.0, you may want to call this method whenever your application moves to the background. An alert view is not dismissed automatically when an application moves to the background. This behavior differs from previous versions of the operating system, where they were canceled automatically when the application was terminated. Dismissing the alert view gives your application a chance to save changes or abort the operation and perform any necessary cleanup in case your application is terminated later.

Janeanjaneczka answered 24/6, 2010 at 9:52 Comment(2)
But Francois asked for a solution without retaining the UIAlertView, if you don't retain (i.e retain count = 0), you can never call dismiss. I didn't try but what the behaviour is when you don't call dismiss? Will it appear again when you move back your app to foreground?Irinairis
Good point, I also follow [alertView show] by [alertView release]. Docs for UIAlertView say "Now, it is up to you to decide whether to dismiss the alert view (and execute its cancellation handler) or leave it visible for when your application moves back to the foreground. Remember that your application can still be terminated while in the background, so some type of action may be necessary in either case.". So i guess you need to decide to keep a reference around or not.Janeanjaneczka
C
0

if you only have one or two specific alert windows you show (as do most apps), then you can just create an assign ivar to the alert:

@property (nonatomic, assign) UIAlertView* alertview;

Then, in the app delegate:

[self.viewController.alertview dismissWithClickedButtonIndex:[self.viewController.alertview cancelButtonIndex] animated:NO];

You can put this in applicationDidEnterBackground: or wherever you see fit. It closes the alert programmatically upon application exit. I've been doing this and it works great.

Contretemps answered 26/8, 2011 at 15:55 Comment(0)
R
0

Create category on UIAlert View

Use http://nshipster.com/method-swizzling/ Swizzle "show" method

Keep track of alert view shown by keeping week references in array.

- When you want to remove all data call Dismiss on saved alert views and empty an array.

Ripping answered 11/11, 2014 at 5:57 Comment(0)
V
0

An alternative solution, based on plkEL's, answer, where the observer is removed when the app is put in the background. If user dismisses the alert by pressing a button, the observer will still be active, but only until the app is put in the background (where the block is run - with an "nil alertView" - and the observer removed).

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
                                                message:message
                                               delegate:alertDelegate
                                      cancelButtonTitle:cancelButtonText
                                      otherButtonTitles:okButtonText, nil];
   [alert show];

   __weak UIAlertView *weakAlert = alert;
   __block __weak id observer = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:      [NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification){
   [weakAlert dismissWithClickedButtonIndex:[weakAlert cancelButtonIndex] animated:NO];
   [[NSNotificationCenter defaultCenter] removeObserver:observer];
    observer = nil;
   }];
Vinificator answered 8/9, 2015 at 12:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.