Dismissing UIAlertViews when entering background state

前端 未结 12 1616
心在旅途
心在旅途 2020-12-02 06:44

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

12条回答
  •  南方客
    南方客 (楼主)
    2020-12-02 07:16

    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 
    
        @interface UIAlertViewAutoDismiss ()  {
            id __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.

提交回复
热议问题