Увольнение UIAlertViews при вводе фонового состояния

Apple рекомендует уволить любого UIAlertViews/UIActionSheets когда ввод фона указывает в iOS 4. Это должно избежать любого беспорядка на части пользователя, когда он повторно запускает приложение позже. Интересно, как я мог изящно распустить весь UIAlertViews сразу, не сохраняя ссылку на него каждый раз я настроил тот...

Какая-либо идея?

31
задан hpique 9 April 2014 в 12:50
поделиться

5 ответов

Меня заинтриговал ответ отца (забавное имя пользователя :)), и мне было интересно, почему он был проголосован ниже.

Поэтому я попробовал.

Вот .m часть подкласса UIAlertView.

Edit: (Cédric) Я добавил способ перехвата вызовов методов делегата и удаления наблюдателя, чтобы избежать множественных регистраций в центре уведомлений.

Все собрано в класс в этом репозитории на github: 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

Все работает отлично. Это здорово, потому что вы можете просто начать использовать его так же, как вы использовали UIAlertView.

У меня не было времени тщательно протестировать его, но я не заметил никакого побочного эффекта.

24
ответ дан 27 November 2019 в 21:27
поделиться

У меня есть это в списке TODO, но мой первый инстинкт - прислушаться к уведомлению UIApplicationWillResignActiveNotification (см. UIApplication) в представлениях, где есть такие вещи, как UIAlertView - здесь вы можете программно удалить представление оповещения с помощью:

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

В обсуждении этого метода даже говорится, для чего он нужен в iOS4!

В iPhone OS 4.0 вы можете захотеть вызывать этот метод всякий раз, когда ваше приложение переходит в фоновый режим. Представление предупреждений не удаляется автоматически, когда приложение переходит в фоновый режим. Такое поведение отличается от предыдущих версий операционной системы, где они отменялись автоматически при завершении приложения. Отключение представления предупреждений дает приложению возможность сохранить изменения или прервать операцию и выполнить необходимую очистку в случае, если приложение будет завершено позже.

1
ответ дан 27 November 2019 в 21:27
поделиться

Самый простой способ - сохранить ссылку на UIAlertView, чтобы вы могли ее отклонить. Конечно, как упомянул Петерт, вы можете сделать это с помощью Уведомления или использовать метод делегата в UIApplication

applicationWillResignActive:

, не всегда означает, что вы переходите в фоновый режим. Например, вы также получите вызов делегата и уведомление (вы получите и то, и другое), когда пользователь получит телефонный звонок или получит SMS-сообщение. Поэтому вам нужно решить, что должно произойти, если пользователь получит SMS и нажмет «Отмена», чтобы остаться в вашем приложении. Возможно, вы захотите убедиться, что ваш UIAlertView все еще существует.

Поэтому я бы отклонил UIAlertView и сохранил состояние в вызове делегата, когда вы действительно переходите в фоновый режим:

applicationDidEnterBackground:

Взгляните на Сессию 105 - Принятие многозадачности на iOS4 из WWDC10, доступную бесплатно на developer.apple.com . Интересно становится в 16:00 мин.

Посмотрите этот рисунок , чтобы понять различные состояния приложения

3
ответ дан 27 November 2019 в 21:27
поделиться

ага. Еще не пробовал, но мне интересно, имеет ли смысл создать подкласс UIAlertView, который прослушивает это уведомление и закрывается, если это так ...

Это будет «автоматически» без сохранения / сохранения вокруг характеристики OP запрашивается. Не забудьте отменить регистрацию для получения уведомления о закрытии (иначе бум!)

12
ответ дан 27 November 2019 в 21:27
поделиться

Я бы предложил добавить категорию в UIAlertview, добавив следующую функцию :

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

И подписаться на UIApplicationWillResignActiveNotification :

[[NSNotificationCenter defaultCenter] addObserver:alertView selector:@selector(hide) name:@"UIApplicationWillResignActiveNotification" object:nil];
26
ответ дан 27 November 2019 в 21:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: