Apple рекомендует уволить любого UIAlertViews/UIActionSheets
когда ввод фона указывает в iOS 4. Это должно избежать любого беспорядка на части пользователя, когда он повторно запускает приложение позже. Интересно, как я мог изящно распустить весь UIAlertViews сразу, не сохраняя ссылку на него каждый раз я настроил тот...
Какая-либо идея?
Меня заинтриговал ответ отца (забавное имя пользователя :)), и мне было интересно, почему он был проголосован ниже.
Поэтому я попробовал.
Вот .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.
У меня не было времени тщательно протестировать его, но я не заметил никакого побочного эффекта.
У меня есть это в списке TODO, но мой первый инстинкт - прислушаться к уведомлению UIApplicationWillResignActiveNotification
(см. UIApplication) в представлениях, где есть такие вещи, как UIAlertView - здесь вы можете программно удалить представление оповещения с помощью:
(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
В обсуждении этого метода даже говорится, для чего он нужен в iOS4!
В iPhone OS 4.0 вы можете захотеть вызывать этот метод всякий раз, когда ваше приложение переходит в фоновый режим. Представление предупреждений не удаляется автоматически, когда приложение переходит в фоновый режим. Такое поведение отличается от предыдущих версий операционной системы, где они отменялись автоматически при завершении приложения. Отключение представления предупреждений дает приложению возможность сохранить изменения или прервать операцию и выполнить необходимую очистку в случае, если приложение будет завершено позже.
Самый простой способ - сохранить ссылку на UIAlertView, чтобы вы могли ее отклонить. Конечно, как упомянул Петерт, вы можете сделать это с помощью Уведомления или использовать метод делегата в UIApplication
applicationWillResignActive:
, не всегда означает, что вы переходите в фоновый режим. Например, вы также получите вызов делегата и уведомление (вы получите и то, и другое), когда пользователь получит телефонный звонок или получит SMS-сообщение. Поэтому вам нужно решить, что должно произойти, если пользователь получит SMS и нажмет «Отмена», чтобы остаться в вашем приложении. Возможно, вы захотите убедиться, что ваш UIAlertView все еще существует.
Поэтому я бы отклонил UIAlertView и сохранил состояние в вызове делегата, когда вы действительно переходите в фоновый режим:
applicationDidEnterBackground:
Взгляните на Сессию 105 - Принятие многозадачности на iOS4 из WWDC10, доступную бесплатно на developer.apple.com . Интересно становится в 16:00 мин.
Посмотрите этот рисунок , чтобы понять различные состояния приложения
ага. Еще не пробовал, но мне интересно, имеет ли смысл создать подкласс UIAlertView, который прослушивает это уведомление и закрывается, если это так ...
Это будет «автоматически» без сохранения / сохранения вокруг характеристики OP запрашивается. Не забудьте отменить регистрацию для получения уведомления о закрытии (иначе бум!)
Я бы предложил добавить категорию в UIAlertview, добавив следующую функцию :
- (void) hide {
[self dismissWithClickedButtonIndex:0 animated:YES];
}
И подписаться на UIApplicationWillResignActiveNotification
:
[[NSNotificationCenter defaultCenter] addObserver:alertView selector:@selector(hide) name:@"UIApplicationWillResignActiveNotification" object:nil];